27 #include <Classes.hpp>
28 #include <Controls.hpp>
29 #include <StdCtrls.hpp>
31 #include <Buttons.hpp>
32 #include <ExtCtrls.hpp>
34 #include <Dialogs.hpp>
35 #include <Graphics.hpp>
36 #include <ComCtrls.hpp>
37 #include <Clipbrd.hpp>
63 #include <Filectrl.hpp>
66 #include <Vcl.HTMLHelpViewer.hpp>
67 #pragma package(smart_init)
68 #pragma link "Vcl.HTMLHelpViewer" //added at v2.0.0 for access to the .chm help file
69 #pragma resource "*.dfm"
95 Screen->Cursor = TCursor(-11);
108 CurDir = AnsiString(GetCurrentDir());
110 UnicodeString FullProgramName = GetModuleName(0);
112 UnicodeString ProgramName = ExtractFileName(FullProgramName);
114 UnicodeString ProgramDirectoryName = ExtractFilePath(FullProgramName);
117 if(!FileExists(ProgramName))
119 if(!SetCurrentDir(ProgramDirectoryName))
121 ShowMessage(
"The working directory does not contain the railway executable file so the program cannot "
122 "open. This is usually because the program has been selected via the right-click taskbar icon though it may "
123 "also happen in other circumstances. It is caused by the Windows operating system re-assigning the "
124 "working directory for some unknown reason, though whether or not it happens appears to depend on the "
125 "Windows update version.\n\n"
126 "To avoid this happening please open the program by double clicking the program icon on the desktop "
127 "if there is one, or the program icon shown in Windows Explorer.");
128 Application->Terminate();
132 CurDir = AnsiString(GetCurrentDir());
190 "program operation will be restricted");
192 Application->HelpFile = AnsiString(
CurDir +
"\\Help.chm");
200 int DispW = (Screen->Width - 64) / 16;
201 int DispH = (Screen->Height - 192) / 16;
324 bool NoConfig =
false;
425 SpeedButton96->Glyph->LoadFromResourceName(0,
"ConcourseGlyph");
491 FontButton->Glyph->LoadFromResourceName(0,
"FontGraphic");
492 HomeButton->Glyph->LoadFromResourceName(0,
"Home");
511 SetGapsButton->Glyph->LoadFromResourceName(0,
"ConnectGaps");
523 CallOnImage->Picture->Bitmap->LoadFromResourceName(0,
"CallingOn");
524 CrashImage->Picture->Bitmap->LoadFromResourceName(0,
"CrashWarning");
525 DerailImage->Picture->Bitmap->LoadFromResourceName(0,
"DerailWarning");
526 SignalStopImage->Picture->Bitmap->LoadFromResourceName(0,
"SignalStopWarning");
527 SPADImage->Picture->Bitmap->LoadFromResourceName(0,
"SPADWarning");
528 TrainFailedImage->Picture->Bitmap->LoadFromResourceName(0,
"TrainFailedWarning");
529 ManualLCDownImage->Picture->Bitmap->LoadFromResourceName(0,
"ManualLCDownImage");
531 DistanceKey->Picture->Bitmap->LoadFromResourceName(0,
"DistanceKey");
536 PrefDirKey->Picture->Bitmap->LoadFromResourceName(0,
"PrefDirKey");
538 TrackLinkedImage->Picture->Bitmap->LoadFromResourceName(0,
"TrackLinkedGraphic");
540 GapsNotSetImage->Picture->Bitmap->LoadFromResourceName(0,
"GapsNotSetGraphic");
541 GapsSetImage->Picture->Bitmap->LoadFromResourceName(0,
"GapsSetGraphic");
556 AnsiString NL =
'\n';
557 const AnsiString TTLabelStr1 =
"Start new train" + NL +
"Start new service from a split" + NL +
"Start new service from another service" + NL +
558 "Start new non-repeating shuttle finish service" + NL +
"Start new shuttle train at a timetabled stop" + NL +
559 "Start new shuttle service from a feeder";
561 const AnsiString TTLabelStr2 =
"Pass" + NL +
"Be joined by another train" + NL +
"Front split" + NL +
"Rear split" + NL +
"Change direction of train" +
562 NL +
"Change service description" + NL +
"Change service maximum speed";
564 const AnsiString TTLabelStr3 =
"Finish && form a new service" + NL +
"Finish && join another train" + NL +
"Finish && exit railway" + NL +
565 "Finish && repeat shuttle, finally remain here" + NL +
"Finish && repeat shuttle, finally form a finishing service" + NL +
566 "Finish non-repeating shuttle feeder service" + NL +
"Finish && remain here";
568 const AnsiString TTLabelStr4 =
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
569 "HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
"HH:MM" + NL +
" " +
572 const AnsiString TTLabelStr5 =
"HH:MM ';' Location" + NL +
"HH:MM ';' HH:MM ';' Location";
574 const AnsiString TTLabelStr6 =
"+ rear element ID - space - front element ID [+ optional ';S']" + NL +
"+ ref. of the train that splits" + NL +
575 "+ other service ref." + NL +
"+ shuttle service ref." + NL +
"+ rear element ID - space - front element ID ';' linked shuttle ref." + NL +
576 "+ linked shuttle service ref. ';' feeder service ref." + NL +
"+ location" + NL +
"+ joining train ref." + NL +
"+ new service ref. + [opt. "
577 "new service Mass%-Power% split]" + NL +
"+ new service ref. + [opt. new service Mass%-Power% split]" + NL +
" " + NL +
578 "+ new description" + NL +
"+ new maximum speed" + NL +
"+ new service ref." + NL +
"+ ref. of train to join" + NL +
579 "+ list of valid exit element IDs (at least 1) separated by spaces" + NL +
"+ linked shuttle service ref.";
581 const AnsiString TTLabelStr7 =
"Arrival OR departure time (program will identify) ';' location [+ optional ';min dwell time in seconds' (arrival only)]" + NL +
582 "Arrival time ';' departure time (with no events between) ';' location [+ optional ';min dwell time in seconds']";
584 const AnsiString TTLabelStr9 =
"Timetable entries" + NL +
"(service references etc.)";
585 const AnsiString TTLabelStr11 =
"Timetable" + NL +
"start time";
587 const AnsiString TTLabelStr12 =
"NB: WITHIN SERVICES commas must" + NL +
"not be used (have special meanings)," + NL +
588 "and semicolons may only be used to" + NL +
"separate service components.";
590 const AnsiString TTLabelStr13 =
"+ linked shuttle service ref. ';' finishing service ref." + NL +
"+ linked shuttle service ref.";
592 const AnsiString TTLabelStr15 =
"Repeat the service + ';' minutes between repeats ';' digit increment ';' number of repeats (last line of service)";
615 if((Screen->Width < 1024) || (Screen->Height < 768))
617 ShowMessage(
"Please note that this program works best with a screen resolution of at least 1024 x 768. Please change if possible");
622 WindowState = wsMaximized;
633 Screen->Cursor = TCursor(-2);
691 char *LocalNumericInformation = setlocale(LC_NUMERIC,
"");
694 if(AnsiString(LocalNumericInformation).Length() == 0)
699 struct lconv *conv = &Locale;
706 catch(
const EFOpenError &e)
710 MessageDlg(e.Message +
" - program must terminate", mtError, But, 0);
711 Application->Terminate();
714 catch(
const Exception &e)
718 AnsiString Message =
"A fatal error occurred during the program setup process, the program must terminate. Message = " + e.Message;
719 MessageDlg(Message, mtError, But, 0);
721 Application->Terminate();
758 catch(
const Exception &e)
775 catch(
const Exception &e)
796 Screen->Cursor = TCursor(-2);
806 Screen->Cursor = TCursor(-2);
820 catch(
const Exception &e)
839 catch(
const Exception &e)
852 UnicodeString strVersion = L
"N/A";
854 VersionSize = GetFileVersionInfoSizeW(Application->ExeName.c_str(), &VersionHandle);
857 pBuffer =
new BYTE[VersionSize];
859 if(GetFileVersionInfoW(Application->ExeName.c_str(), VersionHandle, VersionSize, pBuffer))
861 VS_FIXEDFILEINFO *fi;
865 if(VerQueryValueW(pBuffer, L
"\\", (
void**)&fi, &buflen))
868 strVersion.sprintf(L
"%d.%d.%d", HIWORD(fi->dwFileVersionMS), LOWORD(fi->dwFileVersionMS), HIWORD(fi->dwFileVersionLS));
874 return(L
" v" + strVersion);
890 catch(
const Exception &e)
910 catch(
const Exception &e)
924 if(((TSpeedButton*)Sender)->Down)
935 Screen->Cursor = TCursor(-11);
936 InfoPanel->Caption =
"SELECTING: Filling area with chosen element";
937 bool FillSelectionFlag =
false;
940 UnicodeString MessageStr =
941 "Existing elements won't be overwritten but if the chosen element can be named then any existing named "
942 "elements within or adjacent to the area will have their names removed.\n\n"
943 "Click 'Yes' to fill the area with the chosen element or 'No' to abort.\n\nThis message will not be shown again.";
944 int button = Application->MessageBox(MessageStr.c_str(), L
"", MB_YESNO);
947 FillSelectionFlag =
true;
953 bool TrackLinkingRequiredFlag =
true;
954 bool FoundFlag =
false;
955 std::list<AnsiString> NamedElementList;
1003 NamedElementList.sort();
1004 NamedElementList.unique();
1005 AnsiString CurrentName =
"";
1007 while(!NamedElementList.empty())
1009 CurrentName = NamedElementList.front();
1010 NamedElementList.pop_front();
1011 for(
unsigned int TVNamePos = 0; TVNamePos <
Track->
TrackVector.size(); TVNamePos++)
1060 Screen->Cursor = TCursor(-2);
1071 catch(
const Exception &e)
1084 Screen->Cursor = TCursor(-11);
1115 ShowMessage(
"Incomplete track or other error - see highlighted element (it may be behind this message "
1116 "which can be moved by left clicking the mouse in the title bar and dragging it).");
1122 Screen->Cursor = TCursor(-2);
1129 ShowMessage(
"Unable to set any track links");
1134 Screen->Cursor = TCursor(-2);
1157 ShowMessage(
"Successful Completion");
1158 Screen->Cursor = TCursor(-2);
1161 catch(
const Exception &e)
1183 catch(
const Exception &e)
1203 catch(
const Exception &e)
1223 catch(
const Exception &e)
1242 TFont *TempFont =
new TFont;
1250 TempText.
Font = DisplayFont;
1258 else if(Key ==
'\x1B')
1268 catch(
const Exception &e)
1288 catch(
const Exception &e)
1303 ShowMessage(
"Error, location name being entered without an entry in LNPendingList");
1323 Screen->Cursor = TCursor(-11);
1326 AnsiString ExistingName;
1343 UnicodeString MessageStr = UnicodeString(
"Another location named '") +
LocationNameTextBox->Text +
1344 UnicodeString(
"' already exists. If you continue its name will be erased. Do you wish to continue?");
1345 int button = Application->MessageBox(MessageStr.c_str(), L
"Warning!", MB_YESNO | MB_ICONWARNING);
1349 Screen->Cursor = TCursor(-2);
1361 bool UseExistingPosition =
false;
1370 if(ExistingName !=
"")
1374 UseExistingPosition =
true;
1378 Screen->Cursor = TCursor(-2);
1393 bool UseExistingPosition =
false;
1396 UseExistingPosition =
true;
1400 Screen->Cursor = TCursor(-2);
1413 LocStr = LocStr.Trim();
1423 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
1425 Screen->Cursor = TCursor(-2);
1426 ShowMessage(
"Location name can't begin with 'digit-digit-colon' as that is treated as the start of a time entry");
1435 if(LocStr.Length() > 50)
1437 Screen->Cursor = TCursor(-2);
1438 ShowMessage(
"Location name too long, 50 characters maximum");
1446 for(
int x = 1; x <= LocStr.Length(); x++)
1448 char Ch = LocStr[x];
1452 if(((Ch < 32) && (Ch >= 0)) || (Ch ==
',') || (Ch ==
';'))
1454 Screen->Cursor = TCursor(-2);
1457 "Location name contains one or more invalid characters - must not contain control characters, ';' or ','");
1468 Screen->Cursor = TCursor(-2);
1469 ShowMessage(
"Location name cannot be 'cdt', this name would interfere with the timetable");
1480 bool UseExistingPosition =
false;
1481 if(ExistingName !=
"")
1485 UseExistingPosition =
true;
1489 Screen->Cursor = TCursor(-2);
1498 Screen->Cursor = TCursor(-2);
1501 catch(
const Exception &e)
1522 catch(
const Exception &e)
1536 int Dist = 0, SpeedLimit = 0;
1540 DistanceStr =
"No change";
1545 SpeedStr =
"No change";
1549 if(DistanceStr ==
"No change")
1553 if(SpeedStr ==
"No change")
1569 if(((Dist != -1) && (DistanceStr.Length() > 6)) || ((SpeedLimit != -1) && (SpeedStr.Length() > 6)))
1571 ShowMessage(
"One or more entries too long");
1575 if((DistanceStr ==
"") || (SpeedStr ==
""))
1577 ShowMessage(
"One or more entries blank");
1583 for(
int x = 1; x <= DistanceStr.Length(); x++)
1585 if((DistanceStr[x] <
'0') || (DistanceStr[x] >
'9'))
1587 ShowMessage(
"Track length value must be a positive whole number, or blank for no change");
1595 for(
int x = 1; x <= DistanceStr.Length(); x++)
1597 if((DistanceStr[x] <
'0') || (DistanceStr[x] >
'9'))
1599 ShowMessage(
"Distance must be a positive whole number");
1607 for(
int x = 1; x <= SpeedStr.Length(); x++)
1609 if((SpeedStr[x] <
'0') || (SpeedStr[x] >
'9'))
1611 ShowMessage(
"Speed limit must be a positive whole number, or blank for no change");
1619 for(
int x = 1; x <= SpeedStr.Length(); x++)
1621 if((SpeedStr[x] <
'0') || (SpeedStr[x] >
'9'))
1623 ShowMessage(
"Speed limit must be a positive whole number, or 'Mixed'");
1631 Dist = DistanceStr.ToInt();
1633 if(SpeedLimit != -1)
1635 SpeedLimit = SpeedStr.ToInt();
1644 if(((Dist != -1) && (Dist < 10)) || ((SpeedLimit != -1) && (SpeedLimit < 10)) || ((SpeedLimit != -1) && (SpeedLimit >
TTrain::MaximumSpeedLimit)))
1647 ShowMessage(
"Lengths must be 10m or more, and speeds must be between 10km/h and 400km/h");
1660 bool NamedLocPresent =
false;
1663 for(
int x = LowSelectHLoc; x < HighSelectHLoc; x++)
1665 for(
int y = LowSelectVLoc; y < HighSelectVLoc; y++)
1669 NamedLocPresent =
true;
1674 if(NamedLocPresent && (Dist < 50))
1678 ShowMessage(
"Note: Named location elements are quite short. If they are too short the simulation might be too unrealistic.\n\nThis message will not be shown again.");
1682 if(NamedLocPresent && (Dist > 200))
1686 ShowMessage(
"Note: Named location elements are quite long. If they are too long the simulation might be too unrealistic.\n\nThis message will not be shown again.");
1690 for(
int x = LowSelectHLoc; x < HighSelectHLoc; x++)
1692 for(
int y = LowSelectVLoc; y < HighSelectVLoc; y++)
1729 catch(
const Exception &e)
1752 catch(
const Exception &e)
1764 TMsgDlgButtons Buttons;
1765 Buttons << mbYes << mbNo;
1766 if(MessageDlg(
"This will reset the selected elements to default lengths & speed limits. Proceed?", mtWarning, Buttons, 0) == mrNo)
1785 for(
int x = LowSelectHLoc; x < HighSelectHLoc; x++)
1787 for(
int y = LowSelectVLoc; y < HighSelectVLoc; y++)
1841 throw Exception(
"Error, XLinkPos > 1 in SetOneDefaultTrackLength at " + AnsiString(TrackElement.
HLoc) +
" & " +
1842 AnsiString(TrackElement.
VLoc));
1858 catch(
const Exception &e)
1870 TMsgDlgButtons Buttons;
1871 Buttons << mbYes << mbNo;
1872 if(MessageDlg(
"This will reset ALL track elements to default lengths & speed limits. Proceed?", mtWarning, Buttons, 0) == mrNo)
1894 catch(
const Exception &e)
1923 bool GraphicFoundInVector =
false;
1924 for(TTrack::TUserGraphicVector::iterator UGVIt =
Track->
UserGraphicVector.begin(); UGVIt < Track->UserGraphicVector.end(); UGVIt++)
1926 if(UGMIt->first == UGVIt->FileName)
1928 GraphicFoundInVector =
true;
1932 if(!GraphicFoundInVector)
1934 delete UGMIt->second;
1950 catch(
const Exception &e)
1990 catch(
const Exception &e)
2029 catch(
const Exception &e)
2059 catch(
const Exception &e)
2085 catch(
const Exception &e)
2104 catch(
const Exception &e)
2119 ShowMessage(
"No preferred direction selection");
2123 Screen->Cursor = TCursor(-11);
2130 Screen->Cursor = TCursor(-2);
2133 catch(
const Exception &e)
2146 TMsgDlgButtons Buttons;
2147 Buttons << mbYes << mbNo;
2148 if(MessageDlg(
"Do you really want to clear all preferred directions?", mtWarning, Buttons, 0) == mrNo)
2164 catch(
const Exception &e)
2179 Screen->Cursor = TCursor(-11);
2188 Screen->Cursor = TCursor(-2);
2191 catch(
const Exception &e)
2209 catch(
const Exception &e)
2230 catch(
const Exception &e)
2255 catch(
const Exception &e)
2282 InfoPanel->Caption =
"PRE-START: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
2286 InfoPanel->Caption =
"OPERATING: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
2295 catch(
const Exception &e)
2323 InfoPanel->Caption =
"PRE-START: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
2327 InfoPanel->Caption =
"OPERATING: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
2336 catch(
const Exception &e)
2364 InfoPanel->Caption =
"PRE-START: Select PREFERRED ROUTE start signal, or left click points to change manually";
2368 InfoPanel->Caption =
"OPERATING: Select PREFERRED ROUTE start signal, or left click points to change manually";
2377 catch(
const Exception &e)
2405 InfoPanel->Caption =
"PRE-START: Select PREFERRED ROUTE start signal, or left click points to change manually";
2409 InfoPanel->Caption =
"OPERATING: Select PREFERRED ROUTE start signal, or left click points to change manually";
2418 catch(
const Exception &e)
2453 InfoPanel->Caption =
"PRE-START: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
2457 InfoPanel->Caption =
"OPERATING: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
2466 catch(
const Exception &e)
2481 InfoPanel->Caption =
"ROUTE CANCELLING: Right click on truncate element, first element to cancel (anywhere else to skip)";
2488 catch(
const Exception &e)
2523 catch(
const Exception &e)
2563 catch(
const Exception &e)
2579 UnicodeString MessageStr =
"Please note that the session will be lost if it hasn't been saved. Do you still wish to exit?";
2582 int button = Application->MessageBox(MessageStr.c_str(), L
"Please confirm", MB_YESNO);
2618 catch(
const Exception &e)
2659 catch (
const Exception &e)
2661 TrainController->
StopTTClockMessage(134,
"Railway file failed to load - is the latest program version in use?\nIf so then the file may be corrupt.\n\nError message: " + e.Message);
2662 Screen->Cursor = TCursor(-2);
2676 Screen->Cursor = TCursor(-11);
2677 std::ifstream VecFile(LoadFileName.c_str());
2678 if(!(VecFile.fail()))
2683 bool GraphicsFollow =
false;
2702 TFont *TempFont =
new TFont;
2703 TempFont->Style.Clear();
2704 TempFont->Name =
"MS Sans Serif";
2705 TempFont->Size = 10;
2707 TempFont->Charset = (TFontCharset)(0);
2716 if((LeftExcess > 0) && (RightExcess > 0))
2720 else if((LeftExcess > 0) && (RightExcess <= 0))
2725 else if((LeftExcess <= 0) && (RightExcess > 0))
2737 if((TopExcess > 0) && (BotExcess > 0))
2741 else if((TopExcess > 0) && (BotExcess <= 0))
2746 else if((TopExcess <= 0) && (BotExcess > 0))
2763 if((LastChar ==
'y') || (LastChar ==
'Y'))
2767 ShowMessage(
"Railway not ready for operation so unable to load as a .rly file. Loading as a new railway under development");
2774 Screen->Cursor = TCursor(-2);
2809 ShowMessage(
"File open failed prior to load");
2811 Screen->Cursor = TCursor(-2);
2815 ShowMessage(
"File integrity check failed - unable to load " + LoadFileName +
". Retry using the latest program version. If that fails and the file exists and is spelled correctly then it is probably corrupt.");
2834 Screen->Cursor = TCursor(-11);
2836 if(!(VecFile.fail()))
2864 ShowMessage(
"File open failed prior to save");
2866 Screen->Cursor = TCursor(-2);
2871 catch(
const Exception &e)
2887 catch(
const Exception &e)
2889 Screen->Cursor = TCursor(-2);
2890 UnicodeString MessageStr =
"Unable to save\nError message: " + e.Message;
2907 ShowMessage(
"Failed to find folder " +
IMAGE_DIR_NAME +
" in the folder where 'railway.exe' resides. Image can't be saved");
2911 Screen->Cursor = TCursor(-11);
2914 AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
2918 AnsiString ShortName =
"";
2919 for(
int x = ImageFileName.Length(); x > 0; x--)
2921 if(ImageFileName[x] ==
'\\')
2923 ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
2927 ShowMessage(
"A bitmap file named " + ShortName +
" will be created in the Images folder");
2928 Graphics::TBitmap *RailwayImage =
new Graphics::TBitmap;
2929 RailwayImage->PixelFormat = pf8bit;
2935 RailwayImage->Width = HPosMax - HPosMin;
2936 RailwayImage->Height = VPosMax - VPosMin;
2944 int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
2945 int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
2946 if(NewWidth > RailwayImage->Width)
2948 RailwayImage->Width = NewWidth;
2950 if(NewHeight > RailwayImage->Height)
2952 RailwayImage->Height = NewHeight;
2956 RailwayImage->Canvas->Brush->Color =
clB5G5R5;
2957 TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
2958 RailwayImage->Canvas->FillRect(Rect);
2965 RailwayImage->SaveToFile(ImageFileName);
2966 delete RailwayImage;
2969 Screen->Cursor = TCursor(-2);
2972 catch(
const Exception &e)
2974 Screen->Cursor = TCursor(-2);
2975 UnicodeString MessageStr =
"Unable to write the image to file, it may be too big";
2976 Application->MessageBox(MessageStr.c_str(), L
"", MB_OK | MB_ICONWARNING);
2992 ShowMessage(
"Failed to find folder " +
IMAGE_DIR_NAME +
" in the folder where 'railway.exe' resides. Image can't be saved");
2996 Screen->Cursor = TCursor(-11);
2999 AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
3003 AnsiString ShortName =
"";
3004 for(
int x = ImageFileName.Length(); x > 0; x--)
3006 if(ImageFileName[x] ==
'\\')
3008 ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
3012 ShowMessage(
"A bitmap file named " + ShortName +
" will be created in the Images folder");
3013 Graphics::TBitmap *RailwayImage =
new Graphics::TBitmap;
3014 RailwayImage->PixelFormat = pf8bit;
3019 RailwayImage->Width = HPosMax - HPosMin;
3020 RailwayImage->Height = VPosMax - VPosMin;
3028 int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
3029 int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
3030 if(NewWidth > RailwayImage->Width)
3032 RailwayImage->Width = NewWidth;
3034 if(NewHeight > RailwayImage->Height)
3036 RailwayImage->Height = NewHeight;
3040 RailwayImage->Canvas->Brush->Color =
clB5G5R5;
3041 TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
3042 RailwayImage->Canvas->FillRect(Rect);
3045 for(
int x = 0; x < ((RailwayImage->Width) / 16); x++)
3047 for(
int y = 0; y < ((RailwayImage->Height) / 16); y++)
3056 RailwayImage->SaveToFile(ImageFileName);
3057 delete RailwayImage;
3060 Screen->Cursor = TCursor(-2);
3063 catch(
const Exception &e)
3065 Screen->Cursor = TCursor(-2);
3066 UnicodeString MessageStr =
"Unable to write the image to file, it may be too big";
3067 Application->MessageBox(MessageStr.c_str(), L
"", MB_OK | MB_ICONWARNING);
3082 ShowMessage(
"Failed to find folder " +
IMAGE_DIR_NAME +
" in the folder where 'railway.exe' resides. Image can't be saved");
3086 Screen->Cursor = TCursor(-11);
3089 AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
3093 AnsiString ShortName =
"";
3094 for(
int x = ImageFileName.Length(); x > 0; x--)
3096 if(ImageFileName[x] ==
'\\')
3098 ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
3102 ShowMessage(
"A bitmap file named " + ShortName +
" will be created in the Images folder");
3103 Graphics::TBitmap *RailwayImage =
new Graphics::TBitmap;
3104 RailwayImage->PixelFormat = pf8bit;
3109 RailwayImage->Width = HPosMax - HPosMin;
3110 RailwayImage->Height = VPosMax - VPosMin;
3118 int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
3119 int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
3120 if(NewWidth > RailwayImage->Width)
3122 RailwayImage->Width = NewWidth;
3124 if(NewHeight > RailwayImage->Height)
3126 RailwayImage->Height = NewHeight;
3130 RailwayImage->Canvas->Brush->Color =
clB5G5R5;
3131 TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
3132 RailwayImage->Canvas->FillRect(Rect);
3139 RailwayImage->SaveToFile(ImageFileName);
3140 delete RailwayImage;
3143 Screen->Cursor = TCursor(-2);
3146 catch(
const Exception &e)
3148 Screen->Cursor = TCursor(-2);
3149 UnicodeString MessageStr =
"Unable to write the image to file, it may be too big";
3150 Application->MessageBox(MessageStr.c_str(), L
"", MB_OK | MB_ICONWARNING);
3165 ShowMessage(
"Failed to find folder " +
IMAGE_DIR_NAME +
" in the folder where 'railway.exe' resides. Image can't be saved");
3169 Screen->Cursor = TCursor(-11);
3174 TimetableTimeStr = TimetableTimeStr.SubString(1, 2) +
'.' + TimetableTimeStr.SubString(4, 2) +
'.' + TimetableTimeStr.SubString(7, 2);
3175 AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
3180 AnsiString ShortName =
"";
3181 for(
int x = ImageFileName.Length(); x > 0; x--)
3183 if(ImageFileName[x] ==
'\\')
3185 ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
3189 ShowMessage(
"A bitmap file named " + ShortName +
" will be created in the Images folder");
3190 Graphics::TBitmap *RailwayImage =
new Graphics::TBitmap;
3191 RailwayImage->PixelFormat = pf8bit;
3196 RailwayImage->Width = HPosMax - HPosMin;
3197 RailwayImage->Height = VPosMax - VPosMin;
3205 int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
3206 int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
3207 if(NewWidth > RailwayImage->Width)
3209 RailwayImage->Width = NewWidth;
3211 if(NewHeight > RailwayImage->Height)
3213 RailwayImage->Height = NewHeight;
3217 RailwayImage->Canvas->Brush->Color =
clB5G5R5;
3218 TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
3219 RailwayImage->Canvas->FillRect(Rect);
3233 bool BreakFlag =
false;
3259 RailwayImage->SaveToFile(ImageFileName);
3260 delete RailwayImage;
3263 Screen->Cursor = TCursor(-2);
3266 catch(
const Exception &e)
3268 Screen->Cursor = TCursor(-2);
3269 UnicodeString MessageStr =
"Unable to write the image to file, it may be too big";
3270 Application->MessageBox(MessageStr.c_str(), L
"", MB_OK | MB_ICONWARNING);
3295 Screen->Cursor = TCursor(-11);
3297 if(!(VecFile.fail()))
3325 ShowMessage(
"Railway failed to save - can't open file");
3327 Screen->Cursor = TCursor(-2);
3331 catch(
const Exception &e)
3334 Screen->Cursor = TCursor(-2);
3347 catch(
const Exception &e)
3369 catch(
const Exception &e)
3385 ShowMessage(
"Failed to find folder " +
FORMATTEDTT_DIR_NAME +
" in the folder where 'railway.exe' resides. Timetable can't be exported");
3393 Screen->Cursor = TCursor(-2);
3396 catch(
const Exception &e)
3457 AZOrderButton->Hint = AnsiString(
"Arrange services in alphabetical order Toggle with Shift+ Z");
3459 TimeOrderButton->Hint = AnsiString(
"Arrange services in chronological (time) order Toggle with Shift+ Y");
3479 ActiveTrackElementNameMapEntry.second = 0;
3530 catch(
const Exception &e)
3580 if(TTBLFile.is_open())
3584 while(!TTBLFile.eof())
3587 if((c > 0) && (c < 32) && (c != 13) && (c != 10))
3590 ShowMessage(
"Timetable file contains invalid control characters");
3601 ShowMessage(
"Failed to open timetable file " +
CreateEditTTFileName +
", make sure it's spelled correctly, it exists and isn't open in another application");
3608 if(TTBLFile.is_open())
3618 AZOrderButton->Hint = AnsiString(
"Arrange services in alphabetical order Toggle with Shift+ Z");
3620 TimeOrderButton->Hint = AnsiString(
"Arrange services in chronological (time) order Toggle with Shift+ Y");
3633 char *TimetableEntryString =
new char[10000];
3636 TTBLFile.getline(TimetableEntryString, 10000,
'\0');
3637 if(strlen(TimetableEntryString) > 9997)
3639 ShowMessage(
"Unable to read a line from file " +
CreateEditTTFileName +
".\nEither the file is corrupt or a single service entry exceeds 10,000 characters.");
3643 if(TTBLFile.eof() && (TimetableEntryString[0] ==
'\0'))
3649 AnsiString OneLine(TimetableEntryString);
3653 delete[]TimetableEntryString;
3658 ShowMessage(
"Failed to open timetable file " +
CreateEditTTFileName +
", make sure it's spelled correctly, it exists and isn't open in another application");
3694 ActiveTrackElementNameMapEntry.second = 0;
3720 catch(
const Exception &e)
3722 TrainController->
StopTTClockMessage(139,
"Timetable file failed to load - is the latest program version in use?\nIf so then the file may be corrupt.\n\nError message: " + e.Message);
3723 Screen->Cursor = TCursor(-2);
3742 InfoPanel->Caption =
"Timetable mode: editor hidden";
3749 ShowHideTTButton->Hint =
"Hide the timetable editor to see the railway Shift H";
3754 catch(
const Exception &e)
3795 catch(
const Exception &e)
3836 catch(
const Exception &e)
3856 catch(
const Exception &e)
3869 bool ValidFlag =
true;
3890 TDateTime DummyTime;
3908 ShowMessage(
"One or more times excessive, not permitted to exceed 95 hours");
3912 AnsiString MinsStr = AnsiString(Mins), HrsStr = AnsiString(Hrs);
3915 MinsStr =
"0" + MinsStr;
3919 HrsStr =
"0" + HrsStr;
3923 NewString += HrsStr +
':' + MinsStr;
3940 catch(
const Exception &e)
3953 bool ValidFlag =
true;
3974 TDateTime DummyTime;
3992 ShowMessage(
"One or more times are now before 00:00, this is not permitted");
3996 AnsiString MinsStr = AnsiString(Mins), HrsStr = AnsiString(Hrs);
3999 MinsStr =
"0" + MinsStr;
4003 HrsStr =
"0" + HrsStr;
4007 NewString += HrsStr +
':' + MinsStr;
4023 catch(
const Exception &e)
4061 catch(
const Exception &e)
4075 typedef std::vector<int> TMinVector;
4076 TMinVector MinVector;
4077 AnsiString OneLine = *
TTCurrentEntryIterator, SubStr, First, Second, Third, Fourth, TrainDataLine, NewEntry;
4078 AnsiString ArrivalTime, DepartureTime, FirstTimeLoc, FirstLocation;
4079 int RearStartOrRepeatMins, FrontStartOrRepeatDigits;
4085 bool FirstTimeLocRegistered =
false;
4086 bool Warning, RepeatFlag =
false;
4088 bool EndOfFile =
false;
4089 bool FinalCallFalse =
false;
4090 bool GiveMessagesFalse =
false;
4091 bool CheckLocationsExistInRailwayFalse =
false;
4096 ShowMessage(
"There seem to be one or more errors in the syntax for the selected entry.\n\nPlease correct before inverting. ");
4104 int Pos = OneLine.Pos(
',');
4107 if(OneLine.Length() > 0)
4109 InputVector.push_back(OneLine);
4115 SubStr = OneLine.SubString(1, Pos - 1);
4116 InputVector.push_back(SubStr);
4117 if(Pos == OneLine.Length())
4121 OneLine = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
4137 if(InputVector.size() > 0)
4139 for(
TTEVIterator IPVIt = InputVector.end() - 1; IPVIt >= InputVector.begin(); IPVIt--)
4141 if(((*IPVIt)[1] ==
'R') && (IPVIt == InputVector.end() - 1))
4144 InputVector.erase(IPVIt);
4147 if(IPVIt == InputVector.begin())
4149 TrainDataLine = *IPVIt;
4150 InputVector.erase(IPVIt);
4154 Third, Fourth, RearStartOrRepeatMins, FrontStartOrRepeatDigits, FormatType,
4155 LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
4159 InputVector.erase(IPVIt);
4166 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp") || (Second ==
"cdt") || (Second ==
"dsc") || (Second ==
"cms"))
4174 InputVector.erase(IPVIt);
4179 InputVector.erase(IPVIt);
4184 if(InputVector.size() == 0)
4186 ShowMessage(
"Can't find any actions to invert!");
4190 if(InputVector.size() == 1)
4192 ShowMessage(
"Only one action so there's nothing to invert!");
4209 bool TimeTimeLocFound =
false;
4210 AnsiString LastTimeVal =
"";
4211 for(
TTEVIterator IPVIt = InputVector.begin(); IPVIt < InputVector.end(); IPVIt++)
4213 if((*IPVIt)[1] ==
'W')
4215 *IPVIt = (*IPVIt).SubString(2, (*IPVIt).Length() - 1);
4219 Third, Fourth, RearStartOrRepeatMins, FrontStartOrRepeatDigits, FormatType,
4220 LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
4224 LastTimeVal = Second;
4225 AnsiString Arrival = First +
";" + Third;
4226 AnsiString Departure = Second +
";" + Third;
4228 InputVector.insert(IPVIt, Arrival);
4229 TimeTimeLocFound =
true;
4234 *IPVIt = First +
";<Service finish command>";
4235 LastTimeVal = First;
4240 *IPVIt = LastTimeVal +
";<Service start command>";
4245 *IPVIt = First +
";<Service start command>";
4250 LastTimeVal = First;
4257 ShowMessage(
"Unable to invert this entry");
4262 if(TimeTimeLocFound)
4284 for(
TTEVIterator IPVIt = InputVector.end() - 1; IPVIt >= InputVector.begin(); IPVIt--)
4286 OutputVector.push_back(*IPVIt);
4289 for(
TTEVIterator OPVIt = OutputVector.begin(); OPVIt < OutputVector.end(); OPVIt++)
4291 TimeVector1.push_back((*OPVIt).SubString(1, 5));
4294 for(
TTEVIterator TVIt = TimeVector1.begin(); TVIt < TimeVector1.end(); TVIt++)
4297 Mins = (*TVIt).SubString(4, 2).ToInt();
4298 Hrs = (*TVIt).SubString(1, 2).ToInt();
4299 MinVector.push_back(Mins + (Hrs * 60));
4302 for(TMinVector::iterator MVIt = MinVector.begin(); MVIt < MinVector.end(); MVIt++)
4305 if(MVIt == MinVector.begin())
4312 for(TMinVector::iterator MVIt = MinVector.begin(); MVIt < MinVector.end(); MVIt++)
4317 for(
unsigned int x = 0; x < MinVector.size(); x++)
4320 AnsiString OutVal = OutputVector.at(x);
4321 AnsiString NewOutVal = AnsiTimeVal + OutputVector.at(x).SubString(6, OutputVector.at(x).Length() - 5);
4322 OutputVector.at(x) = NewOutVal;
4337 for(
TTEVIterator OPVIt = OutputVector.begin(); OPVIt < OutputVector.end(); OPVIt++)
4339 First =
""; Second =
""; Third =
""; Fourth =
"";
4341 Third, Fourth, RearStartOrRepeatMins, FrontStartOrRepeatDigits, FormatType,
4342 LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
4348 for(
int x = (*OPVIt).Length(); x > 0; x--)
4350 bool BreakDue =
false;
4351 if((*OPVIt)[x] ==
';')
4355 *OPVIt = OPVIt->SubString(1, x - 1);
4363 if((FormatType !=
TimeLoc) || (OPVIt == OutputVector.begin()) || (OPVIt == OutputVector.end() - 1))
4365 if(FirstTimeLocRegistered)
4367 OutputVector2.push_back(FirstTimeLoc);
4369 FirstTimeLocRegistered =
false;
4370 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
4372 OutputVector2.push_back(First + AnsiString(
';') + Second +
";<linked service reference>");
4376 OutputVector2.push_back(*OPVIt);
4381 if(!FirstTimeLocRegistered)
4383 ArrivalTime = (*OPVIt).SubString(1, 5);
4384 FirstTimeLocRegistered =
true;
4385 FirstTimeLoc = *OPVIt;
4386 FirstLocation = (*OPVIt).SubString(7, (*OPVIt).Length() - 6);
4390 if(FirstLocation == (*OPVIt).SubString(7, (*OPVIt).Length() - 6))
4392 DepartureTime = (*OPVIt).SubString(1, 5);
4393 OutputVector2.push_back(ArrivalTime + AnsiString(
';') + DepartureTime + AnsiString(
';') + FirstLocation);
4394 FirstTimeLocRegistered =
false;
4398 OutputVector2.push_back(FirstTimeLoc);
4399 ArrivalTime = (*OPVIt).SubString(1, 5);
4400 FirstTimeLocRegistered =
true;
4401 FirstTimeLoc = *OPVIt;
4402 FirstLocation = (*OPVIt).SubString(7, (*OPVIt).Length() - 6);
4403 FirstTimeLocRegistered =
true;
4410 AnsiString Remainder =
"";
4411 int Pos = TrainDataLine.Pos(
';');
4412 TrainDataLine = TrainDataLine.SubString(Pos + 1, TrainDataLine.Length() - Pos);
4413 Pos = TrainDataLine.Pos(
';');
4414 if((Pos != 0) && (Pos != TrainDataLine.Length()))
4416 Remainder = TrainDataLine.SubString(Pos, TrainDataLine.Length() - Pos + 1);
4418 TrainDataLine =
"<Service ref>;<Description>" + Remainder;
4419 OutputVector2.insert(OutputVector2.begin(), TrainDataLine);
4422 OutputVector2.insert(OutputVector2.end(),
"<Repeat command if required>");
4427 for(
TTEVIterator OPVIt = OutputVector2.begin(); OPVIt < OutputVector2.end(); OPVIt++)
4429 NewEntry += *OPVIt +
',';
4434 ShowMessage(
"The events in the highlighted service will be listed in reverse order and pasted and highlighted as the next entry. "
4435 "Train data, transit and dwell times match the current entry but the start time is 00:00, ready to be adjusted using the 'Add mins' function "
4436 "with a value corresponding to the required start time in minutes.\n\nService reference, description, start, finish and repeat "
4437 "commands and linked service references remain to be added (indicated by '<...>'), and if this is to be a follow-on service then "
4438 "the train data must be removed.\n\nIf train descriptions or maximum speeds have been changed then the values will probably need to be "
4439 "amended to suit the inverted timetable.\n\nNote that if any minimum dwell times have been added to the original service then these will "
4440 "be stripped off and should be added again if required.\n\nThis message will not be shown again.");
4449 catch(
const Exception &e)
4451 ShowMessage(
"Unable to invert this entry. Error message = " + e.Message);
4498 if(OldVectorPos == 0)
4526 catch(
const Exception &e)
4586 catch(
const Exception &e)
4604 UnicodeString MessageStr =
"Are you sure this entry should be deleted?";
4605 int button = Application->MessageBox(MessageStr.c_str(), L
"Please confirm", MB_YESNO);
4638 if(OldVectorPos == 0)
4666 catch(
const Exception &e)
4687 AnsiString TempStr =
"";
4688 bool ActiveLine =
false;
4713 while(TempStr[TempStr.Length()] ==
',')
4715 TempStr = TempStr.SubString(1, TempStr.Length() - 1);
4750 (*TTCurrentEntryIterator) = TempStr;
4820 catch(
const Exception &e)
4835 ShowMessage(
"Timetable is empty, can't save an empty timetable");
4841 UnicodeString MessageStr =
4842 "This will save the timetable in alphabetical order and the original order will be lost. If this is what is required "
4843 "click 'YES' and this warning will not be shown again, but if it isn't click 'NO'.\n\nIf a new entry has been created it can "
4844 "be copied (to avoid losing it) before reverting to the original order and then it can be pasted and saved.\n\n"
4845 "If the alphabetical order is saved it will become the new original order.";
4848 int button = Application->MessageBox(MessageStr.c_str(), L
"Please Note:", MB_YESNO | MB_ICONWARNING);
4860 UnicodeString MessageStr =
4861 "This will save the timetable in chronological (time) order and the original order will be lost. If this is what is required "
4862 "click 'YES' and this warning will not be shown again, but if it isn't click 'NO'.\n\nIf a new entry has been created it can "
4863 "be copied (to avoid losing it) before reverting to the original order and then it can be pasted and saved.\n\n"
4864 "If the chronological (time) order is saved it will become the new original order.";
4867 int button = Application->MessageBox(MessageStr.c_str(), L
"Please Note:", MB_YESNO | MB_ICONWARNING);
4877 std::ofstream TTBLFile;
4912 if(TTBLFile.is_open())
4929 TTBLFile << (*TEVIterator).c_str() <<
'\0';
4936 ShowMessage(
CreateEditTTFileName +
" failed to open, ensure not already open in another application");
4944 catch(
const Exception &e)
4947 Screen->Cursor = TCursor(-2);
4961 ShowMessage(
"Timetable is empty, can't save an empty timetable");
4965 std::ofstream TTBLFile;
4974 for(
int x =
SaveTTDialog->FileName.Length(); x > 0; x--)
4992 if(TTBLFile.is_open())
5009 TTBLFile << (*TEVIterator).c_str() <<
'\0';
5016 ShowMessage(
CreateEditTTFileName +
" failed to open, ensure not already open in another application");
5024 catch(
const Exception &e)
5038 bool EndOfFile =
false;
5039 bool FinalCallFalse =
false;
5040 bool GiveMessagesTrue =
true;
5041 bool CheckLocationsExistInRailway =
false;
5044 CheckLocationsExistInRailway =
true;
5051 "The basic syntax seems OK but this check is very limited. Other aspects can only be checked by validating the whole timetable with the appropriate railway (.rly) loaded");
5057 catch(
const Exception &e)
5085 bool CheckLocationsExistInRailwayTrue =
true;
5088 Screen->Cursor = TCursor(-11);
5090 if(TTBLFile.is_open())
5096 ShowMessage(
"Timetable integrity OK");
5104 ShowMessage(
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
5106 Screen->Cursor = TCursor(-2);
5116 catch(
const Exception &e)
5178 catch(
const Exception &e)
5240 catch(
const Exception &e)
5277 catch(
const Exception &e)
5292 UnicodeString MessageStr =
"All changes to the timetable will be lost - proceed?";
5293 int button = Application->MessageBox(MessageStr.c_str(), L
"Please confirm", MB_YESNO);
5303 if(TTBLFile.is_open())
5321 char *TimetableEntryString =
new char[10000];
5324 TTBLFile.getline(TimetableEntryString, 10000,
'\0');
5325 if(TTBLFile.eof() && (TimetableEntryString[0] ==
'\0'))
5331 AnsiString OneLine(TimetableEntryString);
5335 delete[]TimetableEntryString;
5340 ShowMessage(
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
5360 catch(
const Exception &e)
5375 ShowMessage(
"Failed to find folder " +
FORMATTEDTT_DIR_NAME +
" in the folder where 'railway.exe' resides. Timetable can't be exported");
5394 Screen->Cursor = TCursor(-2);
5399 catch(
const Exception &e)
5432 catch(
const Exception &e)
5447 UnicodeString MessageStr =
"The timetable has changed.\n\nAre you sure you want to exit without saving it?";
5448 int button = Application->MessageBox(MessageStr.c_str(), L
"Please confirm", MB_YESNO);
5464 catch(
const Exception &e)
5495 UnicodeString MessageStr = UnicodeString(
"This will create separate services from the selected repeat entry. Beware that if the repeating "
5496 "service contains links to another service and has zero as the headcode digit increase for each repeat "
5497 "(i.e. repeats all have the same headcode) then the expanded timetable will fail to validate. "
5498 "In these circumstances please ensure that the headcode changes for each repeat and that all the "
5499 "service references (not necessarily headcodes) for all linked services are unique.\n\n"
5500 "It is recommended to save the expanded timetable using 'Save timetable as' rather than 'Save "
5501 "timetable' in order to keep the original timetable in case the expansion does not provide what "
5502 "is wanted.\n\nContinue?");
5503 int button = Application->MessageBox(MessageStr.c_str(), L
"Warning!", MB_YESNO | MB_ICONWARNING);
5510 std::list<TTrainDataEntry*> PreRepeatList;
5513 std::list<TTrainDataEntry*> RepeatList;
5516 std::list<TTrainDataEntry*>::iterator ListIt;
5524 PreRepeatList.clear();
5528 ShowMessage(
"Timetable must be validated before repeat services can be expanded");
5532 if((*TTCurrentEntryIterator).Pos(
",R;") == 0)
5534 ShowMessage(
"Selected timetable entry is not a repeating service");
5540 std::map<TTrainDataEntry*, AnsiString*> LinkMap;
5541 std::pair<TTrainDataEntry*, AnsiString*> LinkMapEntry;
5543 bool StartTimeFound =
false;
5544 TDateTime DummyTime;
5545 bool BreakFlag =
false;
5546 bool BlankLineFound =
false;
5554 ShowMessage(
"Failed to find a repeat for the selected entry. Please discard the modified timetable"
5555 " which is likely to be corrupt and reload the original.");
5560 AnsiString AnsiMins =
"", AnsiDigits =
"", AnsiRepeats =
"";
5562 while(Rpt[x] !=
';')
5568 while(Rpt[x] !=
';')
5570 AnsiDigits += Rpt[x];
5574 while(x <= Rpt.Length())
5576 AnsiRepeats += Rpt[x];
5579 Mins = AnsiMins.ToInt();
5580 Digits = AnsiDigits.ToInt();
5581 Repeats = AnsiRepeats.ToInt();
5595 StartTimeFound =
true;
5602 BlankLineFound =
true;
5604 if((!BlankLineFound && (*TTEVIt)[1] !=
'*'))
5606 LinkMapEntry.first = TDEPtr;
5607 LinkMapEntry.second = &(*TTEVIt);
5608 LinkMap.insert(LinkMapEntry);
5626 BlankLineFound =
false;
5627 StartTimeFound =
false;
5641 StartTimeFound =
true;
5648 BlankLineFound =
true;
5650 if((!BlankLineFound && (*TTEVIt)[1] !=
'*'))
5660 RepeatList.push_back(TDEPtr);
5661 bool DuplicatePointer;
5664 if((AVIt->Command ==
"Snt-sh") || (AVIt->Command ==
"Sns-sh") || (AVIt->Command ==
"Frh-sh") || (AVIt->Command ==
"Fns-sh") ||
5665 (AVIt->Command ==
"Sns") || (AVIt->Command ==
"Fns") || (AVIt->Command ==
"rsp") || (AVIt->Command ==
"fsp") ||
5666 (AVIt->Command ==
"Sfs") || (AVIt->Command ==
"jbo") || (AVIt->Command ==
"Fjo"))
5668 DuplicatePointer =
false;
5669 for(ListIt = RepeatList.begin(); ListIt != RepeatList.end(); ListIt++)
5671 if(*ListIt == AVIt->LinkedTrainEntryPtr)
5673 DuplicatePointer =
true;
5676 for(ListIt = PreRepeatList.begin(); ListIt != PreRepeatList.end(); ListIt++)
5678 if(*ListIt == AVIt->LinkedTrainEntryPtr)
5680 DuplicatePointer =
true;
5683 if((!DuplicatePointer) && (AVIt->Command !=
"Sns-sh"))
5685 PreRepeatList.push_back(AVIt->LinkedTrainEntryPtr);
5691 while(!PreRepeatList.empty())
5694 PreRepeatList.pop_front();
5697 if((AVIt->Command ==
"Snt-sh") || (AVIt->Command ==
"Sns-sh") || (AVIt->Command ==
"Frh-sh") || (AVIt->Command ==
"Fns-sh") ||
5698 (AVIt->Command ==
"Sns") || (AVIt->Command ==
"Fns") || (AVIt->Command ==
"rsp") || (AVIt->Command ==
"fsp") ||
5699 (AVIt->Command ==
"Sfs") || (AVIt->Command ==
"jbo") || (AVIt->Command ==
"Fjo"))
5701 DuplicatePointer =
false;
5702 for(ListIt = RepeatList.begin(); ListIt != RepeatList.end(); ListIt++)
5704 if(*ListIt == AVIt->LinkedTrainEntryPtr)
5706 DuplicatePointer =
true;
5709 for(ListIt = PreRepeatList.begin(); ListIt != PreRepeatList.end(); ListIt++)
5711 if(*ListIt == AVIt->LinkedTrainEntryPtr)
5713 DuplicatePointer =
true;
5716 if((!DuplicatePointer) && (AVIt->Command !=
"Sns-sh"))
5718 PreRepeatList.push_back(AVIt->LinkedTrainEntryPtr);
5722 RepeatList.push_back(TDEPtr);
5727 for(ListIt = RepeatList.begin(); ListIt != RepeatList.end(); ListIt++)
5732 if(AVIt->Command ==
"Sns-sh")
5734 if(LinkMap.find(AVIt->LinkedTrainEntryPtr) != LinkMap.end())
5736 AnsiString* Feeder = LinkMap.find(AVIt->LinkedTrainEntryPtr)->second;
5737 int FPos = Feeder->Pos(
"F-nshs");
5740 Feeder->Delete(FPos, 6);
5741 Feeder->Insert(
"Fns", FPos);
5745 else if(AVIt->Command ==
"Fns-sh")
5747 if(LinkMap.find(AVIt->NonRepeatingShuttleLinkEntryPtr) != LinkMap.end())
5749 AnsiString* Finisher = LinkMap.find(AVIt->NonRepeatingShuttleLinkEntryPtr)->second;
5750 int SPos = Finisher->Pos(
"Sns-fsh");
5754 int TempPos = SPos + 8;
5755 AnsiString SourceRef =
"";
5756 while((*Finisher)[TempPos] !=
',')
5758 SourceRef += (*Finisher)[TempPos];
5761 AddRefDigits(SourceRef, SPos + 8, *Finisher, (Digits * Repeats));
5762 Finisher->Delete(SPos + 3, 4);
5772 AnsiString* TrainEditEntryPtr;
5774 while(!RepeatList.empty())
5777 if(LinkMap.find(TDEPtr) != LinkMap.end())
5779 TrainEditEntryPtr = LinkMap.find(TDEPtr)->second;
5783 ShowMessage(
"Failed to find an entry link, internal timetable has probably been corrupted, please reload the original timetable");
5787 RepeatList.pop_front();
5789 RpIndex = TrainEditEntryPtr->Pos(
",R;");
5792 TrainEditEntryPtr->Delete(RpIndex, (TrainEditEntryPtr->Length() - RpIndex + 1));
5793 *TrainEditEntryPtr =
"####" + *TrainEditEntryPtr;
5797 ShowMessage(
"Failed to find a repeat entry, internal timetable has probably been corrupted, please reload the original timetable");
5806 int IteratorCount = 0;
5807 AnsiString OutwardShuttleRef =
"", ReturnShuttleRef =
"", FeederRef =
"", FinishRef =
"";
5808 int OutwardShuttlePos = 0, ReturnShuttlePos = 0, FinishPos = 0;
5809 bool FirstPass =
true;
5810 int FirstEntryIterator;
5821 FirstEntryIterator = IteratorCount;
5825 EntryCopy.Delete(1, 4);
5826 int Sns_shPos = EntryCopy.Pos(
"Sns-sh");
5827 int Fns_shPos = EntryCopy.Pos(
"Fns-sh");
5828 int Snt_shPos = EntryCopy.Pos(
"Snt-sh");
5829 int Frh_shPos = EntryCopy.Pos(
"Frh-sh");
5839 int TempPos = Sns_shPos + 7;
5840 ReturnShuttlePos = TempPos;
5841 while(EntryCopy[TempPos] !=
';')
5843 ReturnShuttleRef += EntryCopy[TempPos];
5847 while(EntryCopy[TempPos] !=
',')
5849 FeederRef += EntryCopy[TempPos];
5853 EntryCopy.Delete(ReturnShuttlePos, ReturnShuttleRef.Length() + 1);
5854 EntryCopy.Delete(Sns_shPos + 3, 3);
5859 EntryCopy.Delete(ReturnShuttlePos - 3, FeederRef.Length());
5860 EntryCopy.Insert(ReturnShuttleRef, ReturnShuttlePos - 3);
5861 for(
int x = 1; x <= Repeats; x++)
5863 for(
int Position = 1; Position <= EntryCopy.Length(); Position++)
5865 bool FoundRef =
false;
5866 AnsiString AnsiServRef =
"";
5871 else if(Position == ReturnShuttlePos - 3)
5875 else if((EntryCopy.SubString(Position, 3) ==
"Fns") || (EntryCopy.SubString(Position, 3) ==
"rsp") ||
5876 (EntryCopy.SubString(Position, 3) ==
"fsp") || (EntryCopy.SubString(Position, 3) ==
"Fjo") ||
5877 (EntryCopy.SubString(Position, 3) ==
"jbo"))
5885 while((y <= EntryCopy.Length()) && (EntryCopy[y] !=
';') && (EntryCopy[y] !=
','))
5887 AnsiServRef += EntryCopy[y];
5890 if((x > 1) || Position != ReturnShuttlePos - 3)
5892 AddRefDigits(AnsiServRef, Position, EntryCopy, Digits);
5897 for(
int z = 1; z <= EntryCopy.Length(); z++)
5901 AnsiString NewTime =
AddTimeMinutes(EntryCopy.SubString(z,5), Mins);
5902 EntryCopy.Delete(z, 5);
5903 EntryCopy.Insert(NewTime, z);
5912 else if(Snt_shPos > 0)
5921 AnsiString StartLoc =
"";
5922 int TempPos = Snt_shPos + 7;
5923 int StartLocPos = TempPos;
5924 while(EntryCopy[TempPos] !=
';')
5926 StartLoc += EntryCopy[TempPos];
5930 ReturnShuttlePos = TempPos;
5931 while(EntryCopy[TempPos] !=
',')
5933 ReturnShuttleRef += EntryCopy[TempPos];
5937 EntryCopy.Delete(ReturnShuttlePos, ReturnShuttleRef.Length());
5938 EntryCopy.Delete(StartLocPos, StartLoc.Length() + 1);
5939 EntryCopy.Delete(Snt_shPos + 3, 3);
5940 EntryCopy.Insert(StartLoc, StartLocPos - 3);
5946 ReturnShuttlePos = StartLocPos - 3;
5947 AnsiString TrainDataString =
"";
5949 for(
int x = 1; x <= Repeats; x++)
5953 EntryCopy.Delete(StartLocPos - 3, StartLoc.Length());
5954 EntryCopy.Insert(ReturnShuttleRef, StartLocPos - 3);
5955 EntryCopy.Delete(Snt_shPos, 3);
5956 EntryCopy.Insert(
"Sns", Snt_shPos);
5959 while(EntryCopy[TempPos] !=
';')
5964 while(EntryCopy[TempPos] !=
';')
5969 TrainDataPos = TempPos;
5970 while(EntryCopy[TempPos] !=
',')
5972 TrainDataString += EntryCopy[TempPos];
5976 EntryCopy.Delete(TrainDataPos, TrainDataString.Length() + 1);
5978 for(
int Position = 1; Position <= EntryCopy.Length(); Position++)
5980 bool FoundRef =
false;
5981 AnsiString AnsiServRef =
"";
5986 else if(Position == EntryCopy.Pos(
"Sns") + 4)
5988 ReturnShuttlePos = Position;
5991 else if((EntryCopy.SubString(Position, 3) ==
"Fns") || (EntryCopy.SubString(Position, 3) ==
"rsp") ||
5992 (EntryCopy.SubString(Position, 3) ==
"fsp") || (EntryCopy.SubString(Position, 3) ==
"Fjo") ||
5993 (EntryCopy.SubString(Position, 3) ==
"jbo"))
6001 while((y <= EntryCopy.Length()) && (EntryCopy[y] !=
';') && (EntryCopy[y] !=
','))
6003 AnsiServRef += EntryCopy[y];
6006 if((x > 1) || Position != ReturnShuttlePos)
6008 AddRefDigits(AnsiServRef, Position, EntryCopy, Digits);
6013 for(
int z = 1; z <= EntryCopy.Length(); z++)
6017 AnsiString NewTime =
AddTimeMinutes(EntryCopy.SubString(z,5), Mins);
6018 EntryCopy.Delete(z, 5);
6019 EntryCopy.Insert(NewTime, z);
6028 else if(Fns_shPos > 0)
6037 int TempPos = Fns_shPos + 7;
6038 OutwardShuttlePos = TempPos;
6039 while(EntryCopy[TempPos] !=
';')
6041 OutwardShuttleRef += EntryCopy[TempPos];
6045 FinishPos = TempPos;
6046 while(TempPos <= EntryCopy.Length())
6048 FinishRef += EntryCopy[TempPos];
6052 EntryCopy.Delete(FinishPos, FinishRef.Length() + 1);
6053 EntryCopy.Delete(Fns_shPos + 3, 3);
6056 AddRefDigits(OutwardShuttleRef, OutwardShuttlePos - 3, EntryCopy, Digits);
6061 for(
int x = 1; x <= Repeats; x++)
6065 EntryCopy.Delete(OutwardShuttlePos - 3, OutwardShuttleRef.Length());
6066 EntryCopy.Insert(FinishRef, OutwardShuttlePos - 3);
6068 for(
int Position = 1; Position <= EntryCopy.Length(); Position++)
6070 bool FoundRef =
false;
6071 AnsiString AnsiServRef =
"";
6076 else if(Position == OutwardShuttlePos - 3)
6080 else if((EntryCopy.SubString(Position, 3) ==
"Sns") || (EntryCopy.SubString(Position, 3) ==
"rsp") ||
6081 (EntryCopy.SubString(Position, 3) ==
"fsp") || (EntryCopy.SubString(Position, 3) ==
"Fjo") ||
6082 (EntryCopy.SubString(Position, 3) ==
"jbo"))
6090 while((y <= EntryCopy.Length()) && (EntryCopy[y] !=
';') && (EntryCopy[y] !=
','))
6092 AnsiServRef += EntryCopy[y];
6095 if((x < Repeats) || (AnsiServRef != FinishRef))
6097 AddRefDigits(AnsiServRef, Position, EntryCopy, Digits);
6102 for(
int z = 1; z <= EntryCopy.Length(); z++)
6106 AnsiString NewTime =
AddTimeMinutes(EntryCopy.SubString(z,5), Mins);
6107 EntryCopy.Delete(z, 5);
6108 EntryCopy.Insert(NewTime, z);
6117 else if(Frh_shPos > 0)
6126 int TempPos = Frh_shPos + 7;
6127 OutwardShuttlePos = TempPos;
6128 while(TempPos <= EntryCopy.Length())
6130 OutwardShuttleRef += EntryCopy[TempPos];
6134 EntryCopy.Delete(Frh_shPos, 6);
6135 EntryCopy.Insert(
"Fns", Frh_shPos);
6138 AddRefDigits(OutwardShuttleRef, OutwardShuttlePos - 3, EntryCopy, Digits);
6143 for(
int x = 1; x <= Repeats; x++)
6147 EntryCopy.Delete(Frh_shPos - 6, EntryCopy.Length() - Frh_shPos + 7);
6148 EntryCopy.Insert(
"Frh", Frh_shPos - 6);
6150 for(
int Position = 1; Position <= EntryCopy.Length(); Position++)
6152 bool FoundRef =
false;
6153 AnsiString AnsiServRef =
"";
6158 else if(Position == OutwardShuttlePos - 3)
6162 else if((EntryCopy.SubString(Position, 3) ==
"Sns") || (EntryCopy.SubString(Position, 3) ==
"rsp") ||
6163 (EntryCopy.SubString(Position, 3) ==
"fsp") || (EntryCopy.SubString(Position, 3) ==
"Fjo") ||
6164 (EntryCopy.SubString(Position, 3) ==
"jbo"))
6172 while((y <= EntryCopy.Length()) && (EntryCopy[y] !=
';') && (EntryCopy[y] !=
','))
6174 AnsiServRef += EntryCopy[y];
6177 if((x < Repeats) || (AnsiServRef != FinishRef))
6179 AddRefDigits(AnsiServRef, Position, EntryCopy, Digits);
6184 for(
int z = 1; z <= EntryCopy.Length(); z++)
6188 AnsiString NewTime =
AddTimeMinutes(EntryCopy.SubString(z,5), Mins);
6189 EntryCopy.Delete(z, 5);
6190 EntryCopy.Insert(NewTime, z);
6203 for(
int x = 1; x <= Repeats; x++)
6205 for(
int Position = 1; Position <= EntryCopy.Length(); Position++)
6207 bool FoundRef =
false;
6208 AnsiString AnsiServRef =
"";
6213 else if((EntryCopy.SubString(Position - 1, 1) ==
";") && (EntryCopy.SubString(Position + 3, 1) ==
";") &&
6214 ((EntryCopy.SubString(Position, 3) ==
"Sns") || (EntryCopy.SubString(Position, 3) ==
"Fns") ||
6215 (EntryCopy.SubString(Position, 3) ==
"rsp") || (EntryCopy.SubString(Position, 3) ==
"fsp") ||
6216 (EntryCopy.SubString(Position, 3) ==
"Sfs") || (EntryCopy.SubString(Position, 3) ==
"Fjo") ||
6217 (EntryCopy.SubString(Position, 3) ==
"jbo")))
6225 while((y <= EntryCopy.Length()) && (EntryCopy[y] !=
';') && (EntryCopy[y] !=
','))
6227 AnsiServRef += EntryCopy[y];
6230 AddRefDigits(AnsiServRef, Position, EntryCopy, Digits);
6234 for(
int z = 1; z <= EntryCopy.Length(); z++)
6238 AnsiString NewTime =
AddTimeMinutes(EntryCopy.SubString(z,5), Mins);
6239 EntryCopy.Delete(z, 5);
6240 EntryCopy.Insert(NewTime, z);
6264 catch(
const Exception &e)
6266 ShowMessage(
"The following error occurred during expansion: " + e.Message +
". Please discard the modified timetable"
6267 " which is likely to be corrupt and reload the original.");
6278 int OrigMins = OrigTimeString.SubString(4,2).ToInt();
6279 int Hrs = OrigTimeString.SubString(1,2).ToInt();
6280 OrigMins += MinsToAdd;
6281 while(OrigMins >= 60)
6286 AnsiString MinsStr = AnsiString(OrigMins), HrsStr = AnsiString(Hrs);
6289 MinsStr =
"0" + MinsStr;
6293 HrsStr =
"0" + HrsStr;
6296 return(HrsStr +
":" + MinsStr);
6307 AnsiString AnsiLastDigits = AnsiServRef.SubString(AnsiServRef.Length() - 1, 2);
6308 int LastDigits = AnsiLastDigits.ToInt();
6309 int NewDigits = (LastDigits + Digits) % 100;
6310 AnsiString AnsiNewDigits = AnsiString(NewDigits);
6313 AnsiNewDigits =
"0" + AnsiNewDigits;
6315 EntryCopy = EntryCopy.Delete(Position + AnsiServRef.Length() - 2, 2);
6316 EntryCopy = EntryCopy.Insert(AnsiNewDigits, Position + AnsiServRef.Length() - 2);
6344 catch(
const Exception &e)
6369 catch(
const Exception &e)
6387 catch(
const Exception &e)
6410 catch(
const Exception &e)
6475 catch(
const Exception &e)
6487 PreStartTime, ActiveSegment, PostEnd
6501 Segment = PreStartTime;
6504 if(Segment == PreStartTime)
6511 Segment = ActiveSegment;
6523 if(CurrentStr !=
"")
6525 CurrentStr = CurrentStr.SubString(1, 10);
6526 for(
int x = 1; x < CurrentStr.Length(); x++)
6528 if((CurrentStr[x] < 32) || (CurrentStr[1] > 126))
6530 CurrentStr = CurrentStr.SubString(1, (x - 1));
6539 if(Segment == ActiveSegment)
6564 int SCPos = Entry.Pos(
';');
6565 int CPos = Entry.Pos(
',');
6572 if((CPos == 0) && (SCPos == 0))
6574 Entry = Entry.SubString(1, 12);
6576 else if((CPos > 0) && (SCPos > 0) && (CPos < SCPos))
6578 Entry = Entry.SubString(1, CPos - 1);
6580 else if((CPos > 0) && (SCPos > 0) && (CPos > SCPos))
6582 Entry = Entry.SubString(1, SCPos - 1);
6584 else if((CPos > 0) && (SCPos == 0))
6586 Entry = Entry.SubString(1, CPos - 1);
6590 Entry = Entry.SubString(1, SCPos - 1);
6603 if(Segment == PostEnd)
6612 if(CurrentStr !=
"")
6614 CurrentStr = CurrentStr.SubString(1, 10);
6615 for(
int x = 1; x < CurrentStr.Length(); x++)
6617 if((CurrentStr[x] < 32) || (CurrentStr[1] > 126))
6619 CurrentStr = CurrentStr.SubString(1, (x - 1));
6650 UnicodeString MessageStr =
6651 "If you wish to preserve the original order don't save any changes whilst in alphabetical order.\n\n"
6652 "To preserve the original order use alphabetical order to find the service required, click it to display it,"
6653 " then revert to the original order where the same service will be displayed and can be changed.\n\n"
6654 "This warning won't be shown again but a new warning will be given on attempting to save when in alphabetical order.";
6657 Application->MessageBox(MessageStr.c_str(), L
"IMPORTANT:", MB_OK | MB_ICONWARNING);
6672 std::sort(SortStart, SortEnd);
6674 bool CurrentEntryChanged =
false;
6680 CurrentEntryChanged =
true;
6683 if(!CurrentEntryChanged)
6688 AZOrderButton->Hint = AnsiString(
"Arrange services in original order Toggle with Shift+ Z");
6694 UnicodeString MessageStr =
6695 "Reverting to the original order will discard any changes made whilst in alphabetical order.\n\nTo preserve the changes click 'No', then save the timetable or use 'save as' if you wish to keep the original timetable.\n\nDo you wish to proceed?";
6696 int button = Application->MessageBox(MessageStr.c_str(), L
"Warning!", MB_YESNO | MB_ICONWARNING);
6710 bool CurrentEntryChanged =
false;
6716 CurrentEntryChanged =
true;
6719 if(!CurrentEntryChanged)
6724 AZOrderButton->Hint = AnsiString(
"Arrange services in alphabetical order Toggle with Shift+ Z");
6733 catch(
const Exception &e)
6735 ShowMessage(
"The following error has occurred: " + e.Message +
".\n\nPlease don't save the timetable as it has probably been corrupted - "
6736 "especially likely if the timetable hadn't been validated.\n\nInstead please exit the timetable editor and reload the original."
6737 "\n\nIf the problem persists with a validated timetable please send the railway and original timetable to railwayfeedback@gmail.com"
6758 UnicodeString MessageStr =
6759 "If you wish to preserve the original order don't save any changes whilst in time order.\n\n"
6760 "This warning won't be shown again but a new warning will be given on attempting to save when in time order.";
6763 Application->MessageBox(MessageStr.c_str(), L
"IMPORTANT:", MB_OK | MB_ICONWARNING);
6770 AnsiString Time =
"", StartTime =
"";
6772 bool PreStart =
true, MainBody =
false, PostEnd =
false;
6773 int IteratorCount = 0;
6783 StartTime = (*x).SubString(1,5);
6784 if(((StartTime[1] >=
'0') && (StartTime[1] <=
'9')) &&
6785 ((StartTime[2] >=
'0') && (StartTime[2] <=
'9')) &&
6786 ((StartTime[3] ==
':')))
6788 *x =
"//:58" + (*x);
6795 *x =
"//:57" + (*x);
6801 bool AllCommas =
true;
6802 for(
int a = 1; a < (*x).Length() + 1; a++)
6809 if((*x ==
"") || AllCommas)
6819 *x =
"//:59" + (*x);
6823 StartPos = (*x).Pos(
";Snt");
6826 StartPos = (*x).Pos(
";Sns");
6830 StartPos = (*x).Pos(
";Sfs");
6832 if((StartPos == 0) || (StartPos < 11))
6834 throw Exception(
"No start entry or other error in " + (*x));
6838 while((y > 0) && ((*x)[y] !=
','))
6844 throw Exception(
"No comma prior to time entry in " + (*x));
6846 else if((StartPos - y) < 6)
6848 throw Exception(
"No room for the time entry in " + (*x));
6850 Time = (*x).SubString(StartPos - 5,5);
6856 *x =
":::;;" + (*x);
6861 throw Exception(
"Can't identify entry " + (*x));
6876 std::sort(SortStart, SortEnd);
6881 *x = (*x).SubString(6, (*x).Length() - 5);
6885 bool CurrentEntryChanged =
false;
6891 CurrentEntryChanged =
true;
6894 if(!CurrentEntryChanged)
6899 TimeOrderButton->Hint = AnsiString(
"Arrange services in original order Toggle with Shift+ Y");
6905 UnicodeString MessageStr =
6906 "Reverting to the original order will discard any changes made whilst in time order.\n\nTo preserve the changes click 'No', "
6907 "then save the timetable or use 'save as' if you wish to keep the original timetable.\n\nDo you wish to proceed?";
6908 int button = Application->MessageBox(MessageStr.c_str(), L
"Warning!", MB_YESNO | MB_ICONWARNING);
6922 bool CurrentEntryChanged =
false;
6928 CurrentEntryChanged =
true;
6931 if(!CurrentEntryChanged)
6936 TimeOrderButton->Hint = AnsiString(
"Arrange services in chronological (time) order Toggle with Shift+ Y");
6945 catch(
const Exception &e)
6947 ShowMessage(
"The following error has occurred: " + e.Message +
".\n\nPlease don't save the timetable as it has probably been corrupted - "
6948 "especially likely if the timetable hadn't been validated.\n\nInstead please exit the timetable editor and reload the original."
6949 "\n\nIf the problem persists with a validated timetable please send the railway and original timetable to railwayfeedback@gmail.com"
6960 AnsiString OutStr =
"";
6963 while(x < ConvStr.Length())
6965 if((ConvStr[x] ==
'\r') && (ConvStr[x + 1] ==
'\n'))
6973 OutStr += ConvStr[x];
6977 if(x == ConvStr.Length())
6979 OutStr += ConvStr[x];
6985 while(OutStr[OutStr.Length()] ==
',')
6987 OutStr = OutStr.SubString(1, OutStr.Length() - 1);
7071 bool ValidFlag =
true;
7072 for(
int x = 1; x <= AnsiAddSubText.Length(); x++)
7074 if((AnsiAddSubText[x] >
'9') || (AnsiAddSubText[x] <
'0'))
7082 if(AnsiAddSubText.ToInt() != 0)
7092 InfoPanel->Caption =
"Select option or change entry";
7139 if((*TTCurrentEntryIterator).Pos(
",R;") > 0)
7205 bool ServiceEntry =
true;
7210 bool ServiceEntry =
false;
7222 InfoPanel->Caption =
"Add or change entry then save it, or cancel";
7232 AnsiString((
short)ServiceEntry));
7239 int CommaPos = Data.Pos(
',');
7240 if((CommaPos == 0) && (Data !=
""))
7242 CommaPos = Data.Length() + 1;
7245 if(Data.Length() <= CommaPos)
7249 Data = Data.SubString(CommaPos + 1, Data.Length() - CommaPos);
7288 if(CurrentStr !=
"")
7290 for(
int x = 1; x < CurrentStr.Length(); x++)
7292 if((CurrentStr[x] < 32) || (CurrentStr[1] > 126))
7294 CurrentStr = CurrentStr.SubString(1, (x - 1));
7327 TDateTime DummyTime;
7328 bool TimesPresent =
false;
7336 TimesPresent =
true;
7345 return(TimesPresent);
7372 UnicodeString MessageStr =
"The railway has changed, exit without saving?";
7373 int button = Application->MessageBox(MessageStr.c_str(), L
"Please confirm", MB_YESNO);
7385 Application->Terminate();
7387 catch(
const Exception &e)
7412 catch(
const Exception &e)
7437 catch(
const Exception &e)
7462 catch(
const Exception &e)
7477 AnsiString AnsiButton =
"mbLeft";
7478 if(Button == mbRight)
7480 AnsiButton =
"mbRight";
7514 catch(
const Exception &e)
7525 AnsiString AnsiButton =
"mbLeft";
7526 if(Button == mbRight)
7528 AnsiButton =
"mbRight";
7532 "," + AnsiString(Y));
7544 int NoOffsetX, NoOffsetY;
7546 if(Button == mbRight)
7550 AnsiString Text =
"";
7559 Screen->Cursor = TCursor(-22);
7560 AnsiString OldInfo =
InfoPanel->Caption;
7561 InfoPanel->Caption =
"Railway moving, please don't click the mouse";
7620 bool TrackEraseSuccessfulFlag;
7621 int ErasedTrackVectorPosition;
7622 Screen->Cursor = TCursor(-11);
7624 if(TrackEraseSuccessfulFlag)
7626 if(ErasedTrackVectorPosition > -1)
7659 Screen->Cursor = TCursor(-2);
7668 bool LeadingPointsAtLastElement =
false;
7683 if(!LeadingPointsAtLastElement)
7688 InfoPanel->Caption =
"DISTANCE/SPEED SETTING: Continue or set values (overall length), or right click to cancel/truncate";
7707 InfoPanel->Caption =
"DISTANCE/SPEED SETTING: Can't end on leading points, continue or truncate";
7788 if((TrainID01 > -1) && (TrainID23 > -1))
7883 AnsiString LocName =
"";
7888 if((LocName ==
"") && (Train.
MidElement > -1))
8084 Screen->Cursor = TCursor(-11);
8111 Screen->Cursor = TCursor(-2);
8189 Screen->Cursor = TCursor(-11);
8191 bool TrackLinkingRequiredFlag;
8193 TSpeedButton *TempSpeedButton = 0;
8203 bool InternalChecks =
true;
8204 bool PerformNameSearch =
true;
8212 if(TrackLinkingRequiredFlag)
8241 Screen->Cursor = TCursor(-2);
8255 NewGI.
Width = UGMIt->second->Width;
8256 NewGI.
Height = UGMIt->second->Height;
8282 AnsiString NameString;
8292 unsigned int ValidPosition;
8303 ValidElement = InactiveTrackElement1;
8304 ValidPosition = InactivePair.first;
8309 ValidElement = InactiveTrackElement2;
8310 ValidPosition = InactivePair.second;
8321 InfoPanel->Caption =
"NAMING LOCATIONS: Enter name, 'Carriage Return' to accept, 'Escape' to quit";
8352 bool FinishElement =
false, LeadingPointsAtLastElement =
false;
8353 Screen->Cursor = TCursor(-11);
8389 if(!LeadingPointsAtLastElement)
8394 InfoPanel->Caption =
"DISTANCE/SPEED SETTING: Continue or set values (overall length), or right click to cancel/truncate";
8415 InfoPanel->Caption =
"DISTANCE/SPEED SETTING: Can't end on leading points, need to continue or truncate";
8430 Screen->Cursor = TCursor(-2);
8435 Screen->Cursor = TCursor(-2);
8453 InfoPanel->Caption =
"CONNECTING GAPS: Connecting element selected";
8465 ShowMessage(
"All gaps set");
8493 int TrueX = 0, TrueY = 0;
8494 AnsiString ExistingText =
"";
8496 TFont *ExistingTextFont =
new TFont;
8497 int ExistingTextHPos = 0, ExistingTextVPos = 0;
8503 if((TrueX >= TextPtr->HPos) && (TrueX < (TextPtr->HPos + abs(TextPtr->Font->Height))) && (TrueY >= TextPtr->VPos) && (TrueY <
8504 (TextPtr->VPos + abs(TextPtr->Font->Height))))
8506 ExistingText = TextPtr->TextString;
8507 ExistingTextFont->Assign(TextPtr->Font);
8508 ExistingTextHPos = TextPtr->HPos;
8509 ExistingTextVPos = TextPtr->VPos;
8522 TextBox->Font->Assign(ExistingTextFont);
8524 Text_X = ExistingTextHPos;
8525 Text_Y = ExistingTextVPos;
8543 TextBox->Text =
"New Text: CR=end, ESC=quit";
8547 delete ExistingTextFont;
8649 Screen->Cursor = TCursor(-11);
8684 Screen->Cursor = TCursor(-2);
8688 Screen->Cursor = TCursor(-2);
8802 AnsiString(PDE.
VLoc));
8816 bool PointsChanged =
false;
8817 IDInt ReqPosRouteID(-1);
8819 bool CallonTrue =
true;
8827 ReqPosRouteID, PointsChanged))
8869 float TempSpeedVal = 1;
8938 int DivergingPosition = TrackElement.
Conn[3];
8940 DivergingPosition)))
8954 bool SkipFlashing =
false;
8961 IFE.
TVPos = Position;
8976 SkipFlashing =
true;
8985 IFE.
TVPos = DivergingPosition;
9000 SkipFlashing =
true;
9026 bool SkipFlashing =
false;
9033 IFE.
TVPos = Position;
9049 SkipFlashing =
true;
9069 bool TrainPresent =
false;
9073 int BDVectorPos = -1;
9083 TDateTime TempExcessLCDownTime;
9094 if(TempExcessLCDownTime > TDateTime(0))
9124 AnsiString Message =
9125 AnsiString(
"This will open the level crossing manually (it will show in green).\n\nA manually opened"
9126 " level crossing must be manually closed, and as soon as possible to avoid time penalties.\n\n" "This message will not be shown again."
9171 InfoPanel->Caption =
"PRE-START: Select next route location";
9175 InfoPanel->Caption =
"OPERATING: Select next route location";
9188 bool CallonFalse =
false;
9196 InfoPanel->Caption =
"PRE-START: Select next route location";
9200 InfoPanel->Caption =
"OPERATING: Select next route location";
9222 Screen->Cursor = TCursor(-11);
9224 bool PointsChanged =
false;
9234 float TempSpeedVal = 1;
9243 else if(PointsChanged)
9258 Screen->Cursor = TCursor(-2);
9266 bool CallonFalse =
false;
9271 float TempSpeedVal = 1;
9280 else if(PointsChanged)
9298 Screen->Cursor = TCursor(-2);
9306 catch(
const Exception &e)
9320 AnsiString AnsiButton =
"mbLeft";
9321 if(Button == mbRight)
9323 AnsiButton =
"mbRight";
9328 "," + AnsiString(Y));
9329 if(Button != mbLeft)
9335 Screen->Cursor = TCursor(-22);
9336 AnsiString OldInfo =
InfoPanel->Caption;
9337 InfoPanel->Caption =
"Railway moving, please don't click the mouse";
9345 int HRounding, VRounding;
9418 else if(TempLevel2OperMode ==
Operating)
9421 OperateButton->Glyph->LoadFromResourceName(0,
"PauseGraphic");
9425 else if(TempLevel2OperMode ==
Paused)
9428 OperateButton->Glyph->LoadFromResourceName(0,
"RunGraphic");
9434 else if(TempLevel2OperMode ==
PreStart)
9437 OperateButton->Glyph->LoadFromResourceName(0,
"RunGraphic");
9448 catch(
const Exception &e)
9551 if(CurrentHLoc >= StartHLoc)
9559 if(CurrentVLoc >= StartVLoc)
9583 TRect TempRect(StartHLoc, StartVLoc, CurrentHLoc, CurrentVLoc);
9601 if(CurrentHLoc >= StartHLoc)
9609 if(CurrentVLoc >= StartVLoc)
9633 TRect TempRect(StartHLoc, StartVLoc, CurrentHLoc, CurrentVLoc);
9712 catch(
const Exception &e)
9748 AnsiString AnsiButton =
"mbLeft";
9749 if(Button == mbRight)
9751 AnsiButton =
"mbRight";
9756 Screen->Cursor = TCursor(-2);
9776 Screen->Cursor = TCursor(-11);
9781 if(EndHLoc >= StartHLoc)
9789 if(EndVLoc >= StartVLoc)
9797 if(StartHLoc >= EndHLoc)
9807 if(StartVLoc >= EndVLoc)
9844 Screen->Cursor = TCursor(-2);
9916 if(IATVecPair.second != IATVecPair.first)
9926 int PrefDirPos0, PrefDirPos1, PrefDirPos2, PrefDirPos3;
9936 if(PrefDirPos0 > -1)
9941 if(PrefDirPos1 > -1)
9946 if(PrefDirPos2 > -1)
9951 if(PrefDirPos3 > -1)
9970 if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
9978 bool SelectVectorNamedElement =
false;
9979 AnsiString SelectTextString;
9984 SelectVectorNamedElement =
true;
9988 if(SelectVectorNamedElement)
9990 SelectTextString =
"##**" + TextPtr->TextString;
9994 SelectTextString = TextPtr->TextString;
9996 TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, SelectTextString, TextPtr->Font);
10005 for(TTrack::TUserGraphicVector::iterator UserGraphicPtr =
Track->
UserGraphicVector.begin(); UserGraphicPtr < Track->UserGraphicVector.end();
10008 if((UserGraphicPtr->HPos >= LowSelectHPos) && ((UserGraphicPtr->HPos + UserGraphicPtr->Width) < HighSelectHPos) &&
10009 (UserGraphicPtr->VPos >= LowSelectVPos) && ((UserGraphicPtr->VPos + UserGraphicPtr->Height) < HighSelectVPos))
10022 Screen->Cursor = TCursor(-2);
10028 Screen->Cursor = TCursor(-11);
10034 if(EndHLoc >= StartHLoc)
10042 if(EndVLoc >= StartVLoc)
10050 if(StartHLoc >= EndHLoc)
10060 if(StartVLoc >= EndVLoc)
10093 Screen->Cursor = TCursor(-2);
10125 Screen->Cursor = TCursor(-2);
10150 catch(
const Exception &e)
10187 throw Exception(
"Warning - Utilities->CallLog contains more than 50 items");
10244 catch(
const Exception &e)
10310 for(TTrack::TFailedElementVector::iterator FPVIt =
Track->
FailedPointsVector.begin(); FPVIt < Track->FailedPointsVector.end(); FPVIt++)
10312 if(Now > FPVIt->RepairTime)
10322 for(TTrack::TFailedElementVector::iterator FPVIt =
Track->
FailedSignalsVector.begin(); FPVIt < Track->FailedSignalsVector.end(); FPVIt++)
10324 if(Now > FPVIt->RepairTime)
10334 for(TTrack::TFailedElementVector::iterator FPVIt =
Track->
TSRVector.begin(); FPVIt < Track->TSRVector.end(); FPVIt++)
10336 if(Now > FPVIt->RepairTime)
10356 if(random(TSRRandVal) == 0)
10365 IFE.
TVPos = SimpleTVPos;
10372 "\nSpeed limit of 10km/hour applies until track repaired.");
10503 if(
WholeRailwayMoving && (GetAsyncKeyState(VK_LBUTTON) >= 0) && (GetAsyncKeyState(VK_RBUTTON) >= 0))
10506 Screen->Cursor = TCursor(-2);
10531 bool TrainPresent =
false;
10548 TDateTime TempExcessLCDownTime;
10557 if(TempExcessLCDownTime > TDateTime(0))
10586 bool ElementRemovedFlag =
false;
10603 int RouteNumber1, RouteNumber2, TrainID;
10611 ElementRemovedFlag =
true;
10628 bool WH1 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog1->Left) && (Mouse->CursorPos.x < (ClientOrigin.x +
OutputLog1->Width +
OutputLog1->Left))
10631 bool WH2 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog2->Left) && (Mouse->CursorPos.x < (ClientOrigin.x +
OutputLog2->Width +
OutputLog2->Left))
10634 bool WH3 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog3->Left) && (Mouse->CursorPos.x < (ClientOrigin.x +
OutputLog3->Width +
OutputLog3->Left))
10637 bool WH4 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog4->Left) && (Mouse->CursorPos.x < (ClientOrigin.x +
OutputLog4->Width +
OutputLog4->Left))
10640 bool WH5 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog5->Left) && (Mouse->CursorPos.x < (ClientOrigin.x +
OutputLog5->Width +
OutputLog5->Left))
10643 bool WH6 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog6->Left) && (Mouse->CursorPos.x < (ClientOrigin.x +
OutputLog6->Width +
OutputLog6->Left))
10646 bool WH7 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog7->Left) && (Mouse->CursorPos.x < (ClientOrigin.x +
OutputLog7->Width +
OutputLog7->Left))
10649 bool WH8 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog8->Left) && (Mouse->CursorPos.x < (ClientOrigin.x +
OutputLog8->Width +
OutputLog8->Left))
10652 bool WH9 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog9->Left) && (Mouse->CursorPos.x < (ClientOrigin.x +
OutputLog9->Width +
OutputLog9->Left))
10655 bool WH10 = (Mouse->CursorPos.x >= ClientOrigin.x +
OutputLog10->Left) &&
10698 AnsiString Type[15] =
10700 "Simple",
"Crossover",
"Points",
"Buffers",
"Bridge",
"SignalPost",
"Continuation",
"Platform",
"GapJump",
"FootCrossing",
"Unused",
"Concourse",
10701 "Parapet",
"NamedNonStationLocation",
"Erase"
10706 int ScreenX = Mouse->CursorPos.x -
MainScreen->ClientOrigin.x;
10707 int ScreenY = Mouse->CursorPos.y -
MainScreen->ClientOrigin.y;
10709 AnsiString MouseStr =
"Posx: " + AnsiString(ScreenX) +
"; Posy: " + AnsiString(ScreenY);
10713 AnsiString InARoute =
"No";
10715 HVPair.first = HLoc;
10716 HVPair.second = VLoc;
10717 int RouteNumber = 9999;
10718 int RouteID = 9999;
10719 unsigned int RoutePrefDirPos = 0;
10721 AnsiString COS =
"No";
10729 RouteNumber = R2It->second.first;
10730 RoutePrefDirPos = R2It->second.second;
10738 DevelopmentPanel->Caption = MouseStr +
"; OffH " + OffH +
";OffV " + OffV +
"; TVPos: " + AnsiString(Position) +
"; H: " + AnsiString(HLoc) +
"; V: " +
10739 AnsiString(VLoc) +
"; SpTg: " + AnsiString(TrackElement.
SpeedTag) +
"; Type: " + Type[TrackElement.
TrackType] +
"; Att: " + AnsiString(TrackElement.
Attribute)
10744 TrackElement.
ActiveTrackElementName +
"; InRoute " + InARoute +
"; RtNum " + RouteNumber +
"; RtID " + RouteID +
"; PDVecPos " + RoutePrefDirPos +
" Links: " +
10745 TrackElement.
Link[0] +
"," + TrackElement.
Link[1] +
"," + TrackElement.
Link[2] +
"," + TrackElement.
Link[3] +
" CLPos " +
10910 Screen->Cursor = TCursor(-11);
10933 ExitPair.first = -1;
10934 ExitPair.second = -1;
11167 int RouteStartVecPos;
11183 if(FoundFlag && (RouteStartVecPos > -1))
11199 catch(
const EIdException &e)
11205 catch(
const Exception &e)
11223 InfoPanel->Caption =
"CALLING ON: Select signal for call on";
11237 catch(
const Exception &e)
11251 Screen->Cursor = TCursor(-11);
11295 Screen->Cursor = TCursor(-2);
11298 catch(
const Exception &e)
11312 Screen->Cursor = TCursor(-11);
11356 Screen->Cursor = TCursor(-2);
11359 catch(
const Exception &e)
11373 Screen->Cursor = TCursor(-11);
11418 Screen->Cursor = TCursor(-2);
11421 catch(
const Exception &e)
11435 Screen->Cursor = TCursor(-11);
11479 Screen->Cursor = TCursor(-2);
11482 catch(
const Exception &e)
11496 Screen->Cursor = TCursor(-11);
11537 OperateButton->Glyph->LoadFromResourceName(0,
"PauseGraphic");
11544 OperateButton->Glyph->LoadFromResourceName(0,
"RunGraphic");
11553 OperateButton->Glyph->LoadFromResourceName(0,
"RunGraphic");
11580 if((LeftExcess > 0) && (RightExcess > 0))
11584 else if((LeftExcess > 0) && (RightExcess <= 0))
11589 else if((LeftExcess <= 0) && (RightExcess > 0))
11601 if((TopExcess > 0) && (BotExcess > 0))
11605 else if((TopExcess > 0) && (BotExcess <= 0))
11610 else if((TopExcess <= 0) && (BotExcess > 0))
11626 ZoomButton->Glyph->LoadFromResourceName(0,
"ZoomIn");
11628 Screen->Cursor = TCursor(-2);
11632 catch(
const Exception &e)
11646 Screen->Cursor = TCursor(-11);
11671 Screen->Cursor = TCursor(-2);
11675 catch(
const Exception &e)
11703 catch(
const Exception &e)
11716 CutMenuItem->ShortCut = TextToShortCut(
"Ctrl+X");
11719 catch(
const Exception &e)
11741 ShowMessage(
"Please be aware when pasting that anything inside the pasted area will be overwritten.\n\nThis warning will not be shown again.");
11752 catch(
const Exception &e)
11774 TRect NewSelectRect(TLHCH, TLHCV, BRHCH, BRHCV);
11812 catch(
const Exception &e)
11833 catch(
const Exception &e)
11854 catch(
const Exception &e)
11892 int FlipLinkArray[10] =
11894 0, 7, 8, 9, 4, 5, 6, 1, 2, 3
11915 bool ELinkPosFound =
false, XLinkPosFound =
false;
11916 for(
int y = 0; y < 4; y++)
11918 if(!ELinkPosFound && (PDE.
Link[y] == ELink))
11921 ELinkPosFound =
true;
11923 if(!XLinkPosFound && (PDE.
Link[y] == XLink))
11926 XLinkPosFound =
true;
11935 bool FoundFlag =
false;
11942 if(!PDE.
EntryExitNumber() || !ELinkPosFound || !XLinkPosFound || !FoundFlag)
11945 ShowMessage(
"Unable to re-orientate the preferred directions, these won't be set in the flipped selection");
11964 int MidVPosAfterFlip = ((VerSum * 16) + 15) - MidVPosBeforeFlip;
11972 catch(
const Exception &e)
12010 int MirrorLinkArray[10] =
12012 0, 3, 2, 1, 6, 5, 4, 9, 8, 7
12033 bool ELinkPosFound =
false, XLinkPosFound =
false;
12034 for(
int y = 0; y < 4; y++)
12036 if(!ELinkPosFound && (PDE.
Link[y] == ELink))
12039 ELinkPosFound =
true;
12041 if(!XLinkPosFound && (PDE.
Link[y] == XLink))
12044 XLinkPosFound =
true;
12052 bool FoundFlag =
false;
12059 if(!PDE.
EntryExitNumber() || !ELinkPosFound || !XLinkPosFound || !FoundFlag)
12062 ShowMessage(
"Unable to re-orientate the preferred directions, these won't be set in the mirrored selection");
12081 int MidHPosAfterMirror = ((HorSum * 16) + 15) - MidHPosBeforeMirror;
12083 if(LeftPosAfterMirror < (
SelectRect.left * 16))
12093 catch(
const Exception &e)
12135 int Rot180LinkArray[10] =
12137 0, 9, 8, 7, 6, 5, 4, 3, 2, 1
12157 bool ELinkPosFound =
false, XLinkPosFound =
false;
12158 for(
int y = 0; y < 4; y++)
12160 if(!ELinkPosFound && (PDE.
Link[y] == ELink))
12163 ELinkPosFound =
true;
12165 if(!XLinkPosFound && (PDE.
Link[y] == XLink))
12168 XLinkPosFound =
true;
12176 bool FoundFlag =
false;
12183 if(!PDE.
EntryExitNumber() || !ELinkPosFound || !XLinkPosFound || !FoundFlag)
12186 ShowMessage(
"Unable to re-orientate the preferred directions, these won't be set in the rotated selection");
12206 int MidVPosAfterFlip = ((VerSum * 16) + 15) - MidVPosBeforeFlip;
12218 int MidHPosAfterMirror = ((HorSum * 16) + 15) - MidHPosBeforeMirror;
12220 if(LeftPosAfterMirror < (
SelectRect.left * 16))
12232 catch(
const Exception &e)
12245 Screen->Cursor = TCursor(-11);
12262 int button = Application->MessageBox
12263 (L
"Original selection adjusted to make it square. 'OK' to keep this selection or 'Cancel' to make a new selection",
12264 L
"Left click and hold here to move this message box", MB_OKCANCEL);
12265 if(button == IDCANCEL)
12273 Screen->Cursor = TCursor(-2);
12313 if(IATVecPair.second != IATVecPair.first)
12323 int PrefDirPos0, PrefDirPos1, PrefDirPos2, PrefDirPos3;
12333 if(PrefDirPos0 > -1)
12338 if(PrefDirPos1 > -1)
12343 if(PrefDirPos2 > -1)
12348 if(PrefDirPos3 > -1)
12361 int HighSelectVPos =
SelectRect.bottom * 16;
12367 if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos < HighSelectVPos))
12374 bool SelectVectorNamedElement =
false;
12375 AnsiString SelectTextString;
12380 SelectVectorNamedElement =
true;
12384 if(SelectVectorNamedElement)
12386 SelectTextString =
"##**" + TextPtr->TextString;
12390 SelectTextString = TextPtr->TextString;
12392 TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, SelectTextString, TextPtr->Font);
12402 for(TTrack::TUserGraphicVector::iterator UserGraphicPtr =
Track->
UserGraphicVector.begin(); UserGraphicPtr < Track->UserGraphicVector.end();
12405 if((UserGraphicPtr->HPos >= LowSelectHPos) && ((UserGraphicPtr->HPos + UserGraphicPtr->Width) < HighSelectHPos) && (UserGraphicPtr->VPos >=
12406 LowSelectVPos) && ((UserGraphicPtr->VPos + UserGraphicPtr->Height) < HighSelectVPos))
12432 int RotRightLinkArray[10] =
12434 0, 3, 6, 9, 2, 5, 8, 1, 4, 7
12454 bool ELinkPosFound =
false, XLinkPosFound =
false;
12455 for(
int y = 0; y < 4; y++)
12457 if(!ELinkPosFound && (PDE.
Link[y] == ELink))
12460 ELinkPosFound =
true;
12462 if(!XLinkPosFound && (PDE.
Link[y] == XLink))
12465 XLinkPosFound =
true;
12473 bool FoundFlag =
false;
12480 if(!PDE.
EntryExitNumber() || !ELinkPosFound || !XLinkPosFound || !FoundFlag)
12483 ShowMessage(
"Unable to re-orientate the preferred directions, these won't be set in the rotated selection");
12505 int MidHPosAfterRotate = ((
SelectRect.bottom * 16) - 1) + (
SelectRect.left * 16) - MidVPosBeforeRotate;
12512 Screen->Cursor = TCursor(-2);
12517 catch(
const Exception &e)
12531 Screen->Cursor = TCursor(-11);
12548 int button = Application->MessageBox
12549 (L
"Original selection adjusted to make it square. 'OK' to keep this selection or 'Cancel' to make a new selection",
12550 L
"Left click and hold here to move this message box", MB_OKCANCEL);
12551 if(button == IDCANCEL)
12559 Screen->Cursor = TCursor(-2);
12599 if(IATVecPair.second != IATVecPair.first)
12609 int PrefDirPos0, PrefDirPos1, PrefDirPos2, PrefDirPos3;
12619 if(PrefDirPos0 > -1)
12624 if(PrefDirPos1 > -1)
12629 if(PrefDirPos2 > -1)
12634 if(PrefDirPos3 > -1)
12647 int HighSelectVPos =
SelectRect.bottom * 16;
12653 if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos < HighSelectVPos))
12660 bool SelectVectorNamedElement =
false;
12661 AnsiString SelectTextString;
12666 SelectVectorNamedElement =
true;
12670 if(SelectVectorNamedElement)
12672 SelectTextString =
"##**" + TextPtr->TextString;
12676 SelectTextString = TextPtr->TextString;
12678 TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, SelectTextString, TextPtr->Font);
12688 for(TTrack::TUserGraphicVector::iterator UserGraphicPtr =
Track->
UserGraphicVector.begin(); UserGraphicPtr < Track->UserGraphicVector.end();
12691 if((UserGraphicPtr->HPos >= LowSelectHPos) && ((UserGraphicPtr->HPos + UserGraphicPtr->Width) < HighSelectHPos) && (UserGraphicPtr->VPos >=
12692 LowSelectVPos) && ((UserGraphicPtr->VPos + UserGraphicPtr->Height) < HighSelectVPos))
12718 int RotLeftLinkArray[10] =
12720 0, 7, 4, 1, 8, 5, 2, 9, 6, 3
12740 bool ELinkPosFound =
false, XLinkPosFound =
false;
12741 for(
int y = 0; y < 4; y++)
12743 if(!ELinkPosFound && (PDE.
Link[y] == ELink))
12746 ELinkPosFound =
true;
12748 if(!XLinkPosFound && (PDE.
Link[y] == XLink))
12751 XLinkPosFound =
true;
12759 bool FoundFlag =
false;
12766 if(!PDE.
EntryExitNumber() || !ELinkPosFound || !XLinkPosFound || !FoundFlag)
12769 ShowMessage(
"Unable to re-orientate the preferred directions, these won't be set in the rotated selection");
12792 int MidVPosAfterRotate = ((
SelectRect.bottom * 16) - 1) + (
SelectRect.left * 16) - MidHPosBeforeRotate;
12798 Screen->Cursor = TCursor(-2);
12803 catch(
const Exception &e)
12823 catch(
const Exception &e)
12842 catch(
const Exception &e)
12863 InfoPanel->Caption =
"DISTANCE/SPEED SETTING: Set values or leave blank for no change";
12866 ShowMessage(
"Note: length value will apply to each element's track within the selection.\n\nThis message will not be shown again.");
12876 catch(
const Exception &e)
12894 bool FoundFlag =
false;
12938 catch(
const Exception &e)
12970 Clipboard()->Clear();
12971 Clipboard()->Close();
12974 catch(
const EClipboardException &e)
12980 catch(
const Exception &e)
13000 UnicodeString CountWord =
"There are some track elements without preferred directions.\n\n"
13001 "Do you wish to highlight them (YES) or skip this part of the check (NO)?";
13003 int PD0, PD1, PD2, PD3, HLoc, VLoc, LastHLoc = -2000000, LastVLoc = -2000000;
13004 AnsiString TempInfo =
InfoPanel->Caption;
13007 ShowMessage(
"No preferred directions set.");
13014 InfoPanel->Caption =
"Checking preferred directions - please wait";
13017 LasTHVShortPair.first = -2000000;
13018 LasTHVShortPair.second = -2000000;
13019 Screen->Cursor = TCursor(-11);
13024 bool ELinkFound =
false;
13113 if((LastHLoc != HLoc) || (LastVLoc != VLoc))
13135 Screen->Cursor = TCursor(-2);
13136 int Button = Application->MessageBox(L
"Preferred direction mismatch at a link between the\n"
13137 "highlighted element and an adjacent element.\n\n"
13138 "The highlighted element may be behind this message\n"
13139 "which can be moved by left clicking the mouse in the\n"
13140 "title bar and dragging it.\n\n"
13141 "The mismatch may or may not matter depending\n"
13142 "on routing requirements during operation.\n\n"
13143 "Click 'OK' to ignore and continue checking or 'Cancel'\n"
13144 "to allow correction.", L
"Warning", MB_OKCANCEL | MB_ICONWARNING);
13146 if(Button == IDCANCEL)
13152 Screen->Cursor = TCursor(-11);
13157 bool XLinkFound =
false;
13230 if((LastHLoc != HLoc) || (LastVLoc != VLoc))
13252 Screen->Cursor = TCursor(-2);
13253 int Button = Application->MessageBox(L
"Preferred direction mismatch at a link between the\n"
13254 "highlighted element and an adjacent element.\n\n"
13255 "The highlighted element may be behind this message\n"
13256 "which can be moved by left clicking the mouse in the\n"
13257 "title bar and dragging it.\n\n"
13258 "The mismatch may or may not matter depending\n"
13259 "on routing requirements during operation.\n\n"
13260 "Click 'OK' to ignore and continue checking or 'Cancel'\n"
13261 "to allow correction.", L
"Warning", MB_OKCANCEL | MB_ICONWARNING);
13263 if(Button == IDCANCEL)
13269 Screen->Cursor = TCursor(-11);
13311 CountWord =
"There are many track elements without preferred directions.\n\n"
13312 "Do you wish to highlight them (YES) or skip this part of the check (NO)?";
13316 Screen->Cursor = TCursor(-2);
13317 int Button = Application->MessageBox(CountWord.c_str(), L
"Skip option", MB_YESNO);
13322 ShowMessage(
"Finished");
13326 Screen->Cursor = TCursor(-11);
13342 if((LastHLoc != HLoc) || (LastVLoc != VLoc))
13364 Screen->Cursor = TCursor(-2);
13365 int Button = Application->MessageBox(L
"Preferred direction missing at the highlighted element.\n\n"
13366 "The highlighted element may be behind this message\n"
13367 "which can be moved by left clicking the mouse in the\n"
13368 "title bar and dragging it.\n\n"
13369 "The omission may or may not matter depending\n"
13370 "on routing requirements during operation.\n\n"
13371 "Click 'OK' to ignore and continue checking or 'Cancel'\n"
13372 "to allow correction.", L
"Warning", MB_OKCANCEL | MB_ICONWARNING);
13374 if(Button == IDCANCEL)
13380 Screen->Cursor = TCursor(-11);
13391 if((LastHLoc != HLoc) || (LastVLoc != VLoc))
13413 Screen->Cursor = TCursor(-2);
13414 int Button = Application->MessageBox(L
"Preferred direction missing at the highlighted element.\n\n"
13415 "The highlighted element may be behind this message\n"
13416 "which can be moved by left clicking the mouse in the\n"
13417 "title bar and dragging it.\n\n"
13418 "The omission may or may not matter depending\n"
13419 "on routing requirements during operation.\n\n"
13420 "Click 'OK' to ignore and continue checking or 'Cancel'\n"
13421 "to allow correction.", L
"Warning", MB_OKCANCEL | MB_ICONWARNING);
13423 if(Button == IDCANCEL)
13429 Screen->Cursor = TCursor(-11);
13436 Screen->Cursor = TCursor(-2);
13437 ShowMessage(
"Finished");
13441 catch(
const Exception &e)
13443 Screen->Cursor = TCursor(-2);
13444 ShowMessage(
"Error in preferred direction checking, unable to complete the check");
13459 int PD0 = -1, PD1 = -1, PD2 = -1, PD3 = -1;
13460 int PDLinked0 = -1, PDLinked1 = -1, PDLinked2 = -1, PDLinked3 = -1;
13461 int BidirLinkPos = -1;
13462 bool FoundFlag =
false, BidirOnLink =
false;
13464 if((PD0 == -1) || (PD2 == -1) || (PD3 > -1))
13539 if((BidirLinkPos == -1) || (BidirLinkPos > 3))
13552 if((TVLinkPos == 0) || (TVLinkPos == 2) || (TVLinkPos > 3))
13562 if((TVLinkPos != 1) && (TVLinkPos != 3))
13574 if((PDLinked0 == -1) || (PDLinked2 == -1) || (PDLinked3 > -1))
13585 BidirOnLink =
true;
13589 BidirOnLink =
true;
13598 BidirOnLink =
true;
13602 BidirOnLink =
true;
13611 BidirOnLink =
true;
13615 BidirOnLink =
true;
13654 bool CheckLocationsExistInRailwayTrue =
true;
13658 Screen->Cursor = TCursor(-11);
13659 std::ifstream TTBLFile(AnsiString(
TimetableDialog->FileName).c_str(), std::ios_base::binary);
13660 if(TTBLFile.is_open())
13662 bool SessionFileFalse =
false;
13671 ShowMessage(
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
13673 Screen->Cursor = TCursor(-2);
13677 ShowMessage(
"Timetable integrity check failed - unable to load " +
TimetableDialog->FileName +
". \n\nPlease make sure that you are using the latest program version and that the timetable contains no errors.");
13685 catch(
const Exception &e)
13687 TrainController->
StopTTClockMessage(137,
"Timetable file failed to load - is the latest program version in use?\nIf so then the file may be corrupt.\n\nError message: " + e.Message);
13688 Screen->Cursor = TCursor(-2);
13715 AnsiString LocName =
"";
13720 if((LocName ==
"") && (Train.
MidElement > -1))
13738 if((NextElementPosition > -1) && (NextEntryPos > -1))
13754 if((LocName ==
"") && (Train.
MidElement > -1))
13761 catch(
const Exception &e)
13795 if((LeadElementLocName ==
"") && (MidElementLocName ==
"") && (Train.
LeadElement > -1))
13799 if((MidElementLocName ==
"") && (Train.
MidElement > -1))
13803 if((LeadElementLocName == RequiredLocName) || (MidElementLocName == RequiredLocName))
13805 LocName = RequiredLocName;
13807 else if(LeadElementLocName !=
"")
13809 LocName = LeadElementLocName;
13811 else if(MidElementLocName !=
"")
13813 LocName = MidElementLocName;
13873 int NextElementPos = -1;
13874 int NextEntryPos = -1;
13897 if((NextElementPos > -1) && (NextEntryPos > -1))
13931 catch(
const Exception &e)
13949 AnsiString LocName =
"";
13954 if((LocName ==
"") && (Train.
MidElement > -1))
13962 if((LocName ==
"") && (Train.
MidElement > -1))
13969 catch(
const Exception &e)
13985 UnicodeString MessageStr =
"Please be aware that a train moved from a location prior to its departure time must be returned to that location "
13986 "in order to restore timetable control\n\nThis message will not be shown again\n\nOK to continue, Cancel to abort";
13989 int button = Application->MessageBox(MessageStr.c_str(), L
"", MB_OKCANCEL);
13993 if(button == IDCANCEL)
14015 int NextElementPos = -1;
14016 int NextEntryPos = -1;
14024 if((NextElementPos > -1) && (NextEntryPos > -1))
14044 catch(
const Exception &e)
14058 TTrain *TrainToBeJoinedBy;
14078 AnsiString UnableToJoinIfWaitingToJoinMessage =
"Can't join two trains that are waiting to join under\n"
14079 "timetable control. Manoeuvre them both to the join\n"
14080 "location, make sure they are adjacent, and restore\n"
14081 "timetable control. They will then join at the timetabled\n"
14082 "time, or if that has passed then after 30 seconds.";
14087 ShowMessage(UnableToJoinIfWaitingToJoinMessage);
14094 ShowMessage(UnableToJoinIfWaitingToJoinMessage);
14098 AnsiString TrainToBeJoinedByHeadCode = TrainToBeJoinedBy->
HeadCode;
14100 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
14102 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass + ThisTrain.
Mass);
14109 ThisTrain.
Mass += TrainToBeJoinedBy->
Mass;
14116 AnsiString LocName =
"";
14121 if((LocName ==
"") && (ThisTrain.
MidElement > -1))
14125 if((LocName ==
"") && ThisTrain.
LeadElement > -1)
14129 if((LocName ==
"") && (ThisTrain.
MidElement > -1))
14163 catch(
const Exception &e)
14194 AnsiString LocName =
"";
14199 if((LocName ==
"") && (Train.
MidElement > -1))
14207 if((LocName ==
"") && (Train.
MidElement > -1))
14223 catch(
const Exception &e)
14257 AnsiString OneLine;
14259 int NewLinePos = TTStr.Pos(
'\n');
14262 for(
int x = 0; x < 30; x++)
14264 if((TTStr.Length() > 1) && (NewLinePos <= TTStr.Length()) && (NewLinePos != 0))
14266 OneLine = TTStr.SubString(1, NewLinePos);
14267 if(OneLine ==
"\n")
14271 if(OneLine ==
"Timetable:\n")
14273 TTStr = TTStr.SubString(NewLinePos + 1, TTStr.Length() - NewLinePos);
14274 NewLinePos = TTStr.Pos(
'\n');
14279 TTStr = TTStr.SubString(NewLinePos + 1, TTStr.Length() - NewLinePos);
14280 NewLinePos = TTStr.Pos(
'\n');
14282 else if((TTStr.Length() > 1) && (NewLinePos == 0) && ((TTStr.SubString(3, 1) ==
':') || (TTStr.SubString(1, 5) ==
"Termi")))
14289 if(TTStr.Length() <2)
14293 AnsiString EndStr = OneLine.SubString(8, 5);
14295 if((EndStr ==
"Form ") || (EndStr ==
"Join ") || (EndStr ==
"Exit "))
14302 ShowMessage(
"No timetabled events");
14329 catch(
const Exception &e)
14351 AnsiString OneLine;
14353 int NewLinePos = TTStr.Pos(
'\n');
14356 for(
int x = 0; x < 30; x++)
14358 if((TTStr.Length() > 1) && (NewLinePos <= TTStr.Length()) && (NewLinePos != 0))
14360 OneLine = TTStr.SubString(1, NewLinePos);
14361 if(OneLine ==
"\n")
14365 if(OneLine ==
"Timetable:\n")
14367 TTStr = TTStr.SubString(NewLinePos + 1, TTStr.Length() - NewLinePos);
14368 NewLinePos = TTStr.Pos(
'\n');
14373 TTStr = TTStr.SubString(NewLinePos + 1, TTStr.Length() - NewLinePos);
14374 NewLinePos = TTStr.Pos(
'\n');
14376 else if((TTStr.Length() > 1) && (NewLinePos == 0) && ((TTStr.SubString(3, 1) ==
':') || (TTStr.SubString(1, 5) ==
"Termi")))
14383 if(TTStr.Length() <2)
14387 AnsiString EndStr = OneLine.SubString(8, 5);
14389 if((EndStr ==
"Form ") || (EndStr ==
"Join ") || (EndStr ==
"Exit "))
14396 ShowMessage(
"No timetabled events");
14423 catch(
const Exception &e)
14446 if(Button == mbRight)
14461 int Count = 0, PassNum = 0, SkippedEvents = 0;
14464 ShowMessage(
"This is already the next event, nothing will be skipped");
14470 if((AVEPtr->FormatType ==
TimeTimeLoc) && (AVEPtr->ArrivalTime != AVEPtr->DepartureTime))
14479 if((AVEPtr->Command ==
"cdt") || (AVEPtr->Command ==
"dsc") || (AVEPtr->Command ==
"cms") || (AVEPtr->Command ==
"pas") || ((AVEPtr->FormatType ==
TimeLoc) && (AVEPtr->DepartureTime != TDateTime(-1))))
14490 if((StartStr !=
"Arri") && (StartStr !=
"Pass") && (StartStr !=
"Exit"))
14492 ShowMessage(
"When stopped at a signal the selected next event must be 'Arrive...', 'Pass...', or 'Exit railway...'");
14497 int button = Application->MessageBox(L
"This will skip all events before the selection,\n\nOK to proceed?", L
"", MB_YESNO);
14498 if(button == IDYES)
14501 if(SkipTTLBString[SkipTTLBString.Length()] ==
'\n')
14503 SkipTTLBString = SkipTTLBString.SubString(1, (SkipTTLBString.Length() - 1));
14507 +
" significant events skipped until " + SkipTTLBString;
14519 int Count = 0, PassNum = 0, SkippedEvents = 0;
14524 ShowMessage(
"This is already the next event, nothing will be skipped");
14533 ShowMessage(
"This is already the next event after the departure, nothing will be skipped");
14540 if(AVEPtr->DepartureTime > TDateTime(0))
14557 if((AVEPtr->Command ==
"cdt") || (AVEPtr->Command ==
"dsc") || (AVEPtr->Command ==
"cms") || (AVEPtr->Command ==
"pas") ||
14558 ((AVEPtr->FormatType ==
TimeLoc) && (AVEPtr->DepartureTime > TDateTime(0))) ||
14578 ShowMessage(
"When stopped at a location the selected next event must either occur at the same location or be 'Arrive...', 'Pass...', or 'Exit railway...'");
14589 UnicodeString Message =
"This will skip all events before the selection.\n\nOK to proceed?";
14592 Message =
"This will skip all events between the departure and the selection.\n\n"
14593 "Note that no more events may be skipped for this train until after\n"
14594 "it departs from the current location\n\nOK to proceed?";
14596 int button = Application->MessageBox(Message.c_str(), L
"", MB_YESNO);
14597 if(button == IDYES)
14601 if(SkipTTLBString[SkipTTLBString.Length()] ==
'\n')
14603 SkipTTLBString = SkipTTLBString.SubString(1, (SkipTTLBString.Length() - 1));
14609 AnsiString(Train.
TrainSkippedEvents) +
" significant events skipped until " + SkipTTLBString;
14620 AnsiString(Train.
TrainSkippedEvents) +
" significant events skipped after the departure until " + SkipTTLBString;
14636 catch(
const Exception &e)
14645 TShiftState Shift,
int X,
int Y)
14656 int Count = 0, AVPtrIncrement = 0;
14658 int PosArDep = ReminderString.Pos(
"Arrive & depart");
14659 int PosArr = ReminderString.Pos(
"Arrive at");
14660 int PosDep = ReminderString.Pos(
"Depart from");
14665 AnsiString DepTimeFromListBox = ReminderString.SubString(1, 5);
14667 if((AVEPtr->FormatType ==
TimeTimeLoc) && (AVEPtr->ArrivalTime != AVEPtr->DepartureTime))
14675 int PosLoc = ReminderString.Pos(AVEPtr->LocationName);
14677 if((AVEPtr->FormatType !=
TimeTimeLoc) || (PosDep == 0) || (PosLoc == 0) || (DepTimeFromAVEPtr != DepTimeFromListBox))
14688 if(ReminderString[ReminderString.Length()] ==
'\n')
14690 ReminderString = ReminderString.SubString(1, (ReminderString.Length() - 1));
14692 int PosFjo = ReminderString.Pos(
"Join ");
14695 ShowMessage(
"Reminders cannot be given for 'Join XXXX' events (where XXXX is the joining service). For a train join warning set a reminder "
14696 "for the joining train at its 'Joined by XXXX' event");
14703 ShowMessage(
"There is already a warning at this event, there is no need for a reminder where there is already a warning");
14711 Msg = L
"This will set a reminder at '" + ReminderString + L
"'\n(notifications given for arrival only).\n\nOK to proceed?";
14715 Msg = L
"This will set a reminder at '" + ReminderString + L
"'.\n\nOK to proceed?";
14717 int button = Application->MessageBox(Msg.c_str(), L
"", MB_YESNO);
14718 if(button == IDYES)
14728 (AVPtr + AVPtrIncrement)->Reminder = 4;
14731 else if(PosArr > 0)
14734 if((AVPtr + AVPtrIncrement)->Reminder == 2)
14736 (AVPtr + AVPtrIncrement)->Reminder = 4;
14741 (AVPtr + AVPtrIncrement)->Reminder = 3;
14744 else if(PosDep > 0)
14747 if((AVPtr + AVPtrIncrement)->Reminder == 3)
14749 (AVPtr + AVPtrIncrement)->Reminder = 4;
14754 (AVPtr + AVPtrIncrement)->Reminder = 2;
14759 (AVPtr + AVPtrIncrement)->Reminder = 1;
14762 ReminderString +
"'.";
14779 catch(
const Exception &e)
14860 catch(
const Exception &e)
14877 catch(
const Exception &e)
14895 while((NewServiceActionEntryPtr->
Command !=
"Fns") && (NewServiceActionEntryPtr->
Command !=
"Fns-sh") && (NewServiceActionEntryPtr->
Command !=
"F-nshs") &&
14896 (NewServiceActionEntryPtr->
Command !=
"Frh-sh"))
14898 NewServiceActionEntryPtr++;
14901 ShowMessage(
"No follow-on service found, option unavailable");
14908 UnicodeString MessageStr =
"This action will skip all timetabled events until follow-on service " + Train.
FollowOnServiceRef +
" reaches this location\n\nOK to proceed?";
14909 if(NewServiceActionEntryPtr->
Command ==
"Fns")
14913 int button = Application->MessageBox(MessageStr.c_str(), L
"", MB_YESNO);
14925 else if(NewServiceActionEntryPtr->
Command ==
"Fns-sh")
14929 int button = Application->MessageBox(MessageStr.c_str(), L
"", MB_YESNO);
14941 else if(NewServiceActionEntryPtr->
Command ==
"Frh-sh")
14945 int button = Application->MessageBox(MessageStr.c_str(), L
"", MB_YESNO);
14957 else if(NewServiceActionEntryPtr->
Command ==
"F-nshs")
14961 int button = Application->MessageBox(MessageStr.c_str(), L
"", MB_YESNO);
14975 ShowMessage(
"Option unavailable");
14992 catch(
const Exception &e)
15004 bool Condition4Met =
false;
15006 NextServiceRef =
"";
15011 if(AVEPtr->Command ==
"Fns")
15013 Condition4Met =
true;
15014 NextServiceEntryPtr = AVEPtr->LinkedTrainEntryPtr;
15018 if(AVEPtr->Command ==
"Fns-sh")
15020 Condition4Met =
true;
15023 NextServiceEntryPtr = AVEPtr->NonRepeatingShuttleLinkEntryPtr;
15024 NextServiceRef = NextServiceEntryPtr->
HeadCode;
15028 NextServiceEntryPtr = AVEPtr->LinkedTrainEntryPtr;
15033 if(AVEPtr->Command ==
"Frh-sh")
15041 Condition4Met =
true;
15042 NextServiceEntryPtr = AVEPtr->LinkedTrainEntryPtr;
15047 if(AVEPtr->Command ==
"F-nshs")
15049 Condition4Met =
true;
15050 NextServiceEntryPtr = AVEPtr->LinkedTrainEntryPtr;
15051 NextServiceRef = NextServiceEntryPtr->
HeadCode;
15060 if(AVEPtr->LocationName == CurLoc)
15062 if((AVEPtr->FormatType ==
TimeTimeLoc) || ((AVEPtr->FormatType ==
TimeLoc) && (AVEPtr->ArrivalTime > TDateTime(0))) || (AVEPtr->Command ==
"pas") )
15086 int SkippedEvents = 0;
15089 if((AVEPtr->Command ==
"cdt") || (AVEPtr->Command ==
"dsc") || (AVEPtr->Command ==
"cms") || (AVEPtr->Command ==
"pas") || (AVEPtr->SequenceType ==
FinishSequence) ||
15090 ((AVEPtr->FormatType ==
TimeLoc) && (AVEPtr->DepartureTime != TDateTime(-1))))
15109 +
" significant events skipped before it became the new service";
15117 catch(
const Exception &e)
15132 bool LocFound =
false;
15134 int SkippedEvents = 0;
15136 for(AVEPtr = Train.
ActionVectorEntryPtr; AVEPtr <= &Train.TrainDataEntryPtr->ActionVector.back(); AVEPtr++)
15155 else if(AVEPtr->
Command ==
"pas")
15174 ShowMessage(
"New service location not found");
15181 +
" significant events skipped before the new service arrived at " + LocationName;
15189 catch(
const Exception &e)
15224 catch(
const Exception &e)
15240 UnicodeString MessageStr =
"Please be aware that a train moved from a location prior to its departure time must be returned to that location "
15241 "in order to restore timetable control\n\nThis message will not be shown again\n\nOK to continue, Cancel to abort";
15244 int button = Application->MessageBox(MessageStr.c_str(), L
"", MB_OKCANCEL);
15248 if(button == IDCANCEL)
15256 if(NextElementPos < 0)
15258 throw Exception(
"Error, no element in front in PassRedSignalMenuItemClick");
15269 throw Exception(
"Error, next element not a signal type in PassRedSignalMenuItemClick");
15283 catch(
const Exception &e)
15299 UnicodeString MessageStr =
"Please be aware that a train moved from a location prior to its departure time must be returned to (or still be at) that location "
15300 "in order to restore timetable control\n\nThis message will not be shown again\n\nOK to continue, Cancel to abort";
15303 int button = Application->MessageBox(MessageStr.c_str(), L
"", MB_OKCANCEL);
15307 if(button == IDCANCEL)
15325 int NextElementPos = -1;
15327 int NextEntryPos = -1;
15335 if((NextElementPos > -1) && (NextEntryPos > -1))
15345 catch(
const Exception &e)
15364 UnicodeString Message = UnicodeString(Train.
HeadCode) +
" will be removed from the railway - proceed?";
15365 int button = Application->MessageBox(Message.c_str(), L
"Please confirm", MB_YESNO);
15378 AnsiString LocName =
"";
15383 if((LocName ==
"") && (Train.
MidElement > -1))
15391 if((LocName ==
"") && (Train.
MidElement > -1))
15443 int FirstRouteElementVecPos = LeadTrackElement.
Conn[Train.
LeadExitPos];
15453 bool FirstPass =
true;
15460 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
15547 catch(
const Exception &e)
15562 Application->Terminate();
15588 UnicodeString MessStr =
"";
15591 MessStr = UnicodeString(
"The railway and the timetable have both changed, exit without saving either?");
15595 MessStr = UnicodeString(
"The railway has changed, exit without saving?");
15599 MessStr = UnicodeString(
"The timetable has changed, exit without saving?");
15601 int button = Application->MessageBox(MessStr.c_str(), L
"Please confirm", MB_YESNO);
15613 UnicodeString MessageStr =
"Please note that the session will be lost if it hasn't been saved. Do you still wish to exit?";
15616 int button = Application->MessageBox(MessageStr.c_str(), L
"Please confirm", MB_YESNO);
15636 catch(
const Exception &e)
15650 if((Shift.Contains(ssAlt)) && (Shift.Contains(ssCtrl)))
15663 else if(Key ==
'3')
15675 else if(Key ==
'4')
15679 else if(Key ==
'5')
15681 TMsgDlgButtons Buttons;
15682 Buttons << mbYes << mbNo;
15683 if(MessageDlg(
"Do you wish to allow signals next to bridges? If so please be aware that routes cannot be truncated to these signals.",
15684 mtWarning, Buttons, 0) == mrYes)
15694 else if(Shift.Contains(ssCtrl) && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
15698 else if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl) && !Shift.Contains(ssAlt))
15710 if((Key != VK_SHIFT) && (Key != VK_CONTROL))
15728 else if(Key == VK_DOWN)
15735 else if(Key == VK_LEFT)
15742 else if(Key == VK_RIGHT)
15749 else if(Key == VK_HOME)
15757 else if(Key == VK_END)
15764 else if(Key == VK_END)
15779 if(Shift.Contains(ssShift) && !Shift.Contains(ssAlt) && !Shift.Contains(ssCtrl) &&
NewHomeButton->Enabled &&
NewHomeButton->Visible)
15791 if(!Shift.Contains(ssCtrl))
15860 if(Key ==
'S' || Key ==
's')
15871 if(Shift.Contains(ssShift))
15886 if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl) && !Shift.Contains(ssAlt))
15933 if(Shift.Contains(ssCtrl) && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
15939 if(Key ==
'S' || Key ==
's')
15945 if(!Shift.Contains(ssCtrl) && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
15956 if(!Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
15963 if(!Shift.Contains(ssShift) && Shift.Contains(ssCtrl))
15969 if(Key ==
'S' || Key ==
's')
15975 if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
15996 if(!Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
16003 if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
16009 if(Key ==
'S' || Key ==
's')
16014 else if(Key ==
'H' || Key ==
'h')
16027 if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
16106 if(
SaveTTButton->Enabled && (Key ==
'T' || Key ==
't'))
16129 if(
FloatingInfoMenu->Enabled && !Shift.Contains(ssAlt) && Shift.Contains(ssCtrl) && Shift.Contains(ssShift))
16131 if(Key ==
'I' || Key ==
'i')
16135 if(Key ==
'S' || Key ==
's')
16139 else if(Key ==
'T' || Key ==
't')
16143 else if(Key ==
'L' || Key ==
'l')
16151 catch(
const Exception &e)
16161 if((Key != VK_SHIFT) && (Key != VK_CONTROL))
16283 catch(
const Exception &e)
16296 Application->HelpKeyword(u
"Introduction");
16298 catch(
const Exception &e)
16308 const UnicodeString Link =
"http://www.railwayoperationsimulator.com";
16309 ::ShellExecute(Handle, NULL, (Link).c_str(), NULL, NULL, SW_SHOWNORMAL);
16332 catch(
const Exception &e)
16358 catch(
const Exception &e)
16384 catch(
const Exception &e)
16440 bool ErrorFlag =
false, TooBigFlag =
false;
16461 if(!ErrorFlag && !TooBigFlag)
16471 int KPH = (MPH * 1.609344) + 0.5;
16478 int MPH = (KPH * 0.621371) + 0.5;
16489 catch(
const EConvertError &ec)
16494 catch(
const Exception &e)
16529 bool ErrorFlag =
false, TooBigFlag =
false;
16550 if(!ErrorFlag && !TooBigFlag)
16560 int KW = (HP * 0.745699872) + 0.5;
16567 int HP = (KW * 1.340482574) + 0.5;
16578 catch(
const EConvertError &ec)
16583 catch(
const Exception &e)
16596 bool ErrorFlag =
false, TooBigFlag =
false;
16617 if(!ErrorFlag && !TooBigFlag)
16627 int KPH = (MPH * 1.609344) + 0.5;
16634 int MPH = (KPH * 0.621371) + 0.5;
16645 catch(
const EConvertError &ec)
16650 catch(
const Exception &e)
16664 bool ErrorFlag =
false, TooLongFlag =
false;
16667 for(
int x = 1; x <=
MileEdit->Text.Length(); x++)
16679 for(
int x = 1; x <=
ChainEdit->Text.Length(); x++)
16691 for(
int x = 1; x <=
YardEdit->Text.Length(); x++)
16703 TooLongFlag =
true;
16706 if(!ErrorFlag && !TooLongFlag)
16708 int Miles = 0, Chains = 0, Yards = 0, Metres = 0;
16721 Metres = int((Miles * 1609.344) + (Chains * 20.1168) + (Yards * 0.9144) + 0.5);
16730 catch(
const EConvertError &ec)
16735 catch(
const Exception &e)
16766 catch(
const Exception &e)
16803 "Changes have been made to the timetable clock - you may wish to save a session before resuming operation.\n\nTo cancel all changes re-click the 'Adjust the timetable clock' button then click the reset button BEFORE resuming operation.";
16812 catch(
const Exception &e)
16830 catch(
const Exception &e)
16849 catch(
const Exception &e)
16868 catch(
const Exception &e)
16887 catch(
const Exception &e)
16906 catch(
const Exception &e)
16925 catch(
const Exception &e)
16944 catch(
const Exception &e)
16964 catch(
const Exception &e)
16983 catch(
const Exception &e)
16997 double TTClockIncrement = 1.0 / 24;
17003 catch(
const Exception &e)
17017 double TTClockIncrement = 1.0 / 144;
17023 catch(
const Exception &e)
17037 double TTClockIncrement = 1.0 / 1440;
17043 catch(
const Exception &e)
17100 catch(
const Exception &e)
17114 InfoPanel->Caption =
"PRE-START: Presetting automatic signal routes";
17125 Screen->Cursor = TCursor(-11);
17127 bool PointsChanged, AtLeastOneSet =
false;
17128 int LastIteratorValue = 0;
17137 AtLeastOneSet =
true;
17154 ShowMessage(
"No presettable automatic signal routes are available");
17156 Screen->Cursor = TCursor(-2);
17159 catch(
const Exception &e)
17174 int DispW = (
Interface->Width - 64 - 16) / 16;
17176 int DispH = (
Interface->Height - 192) / 16;
17211 catch(
const Exception &e)
17237 SigImagePanel->Caption =
"Signals will be on the right hand side of the track";
17254 SigImagePanel->Caption =
"Signals will be on the left hand side of the track";
17262 catch(
const Exception &e)
17281 bool TooBigFlag =
false, BadCharsFlag =
false;
17286 for(
int x = 1; x <=
MTBFEditBox->Text.Length(); x++)
17290 BadCharsFlag =
true;
17303 ShowMessage(
"Maximum value allowed is 9999");
17312 ShowMessage(
"Value must be a whole number with no special characters");
17329 catch(
const Exception &e)
17347 "Values can only be entered or changed in Pre-Start mode\ni.e. after selecting 'Operate railway' but before clicking 'Run'");
17351 catch(
const Exception &e)
17383 catch(
const Exception &e)
17409 catch(
const Exception &e)
17425 catch(
const Exception &e)
17446 catch(
const Exception &e)
17470 catch(
const Exception &e)
17487 catch(
const Exception &e)
17504 catch(
const Exception &e)
17520 ShowMessage(
"No boxes ticked!");
17524 Screen->Cursor = TCursor(-11);
17525 AnsiString TTTitle;
17539 ShowMessage(
"Analysis complete and file created");
17544 Screen->Cursor = TCursor(-2);
17547 catch(
const Exception &e)
17565 catch(
const Exception &e)
17579 int LengthInt, SpeedInt;
17580 NoConfigFile =
false;
17581 std::ifstream ConfigFile((
CurDir +
"\\Config.txt").c_str());
17582 if(ConfigFile.fail())
17584 NoConfigFile =
true;
17588 SigImagePanel->Caption =
"Signals will be on the left hand side of the track";
17594 "This program is free software released under the terms of the GNU General Public License Version 3, as published by the Free Software Foundation. "
17595 " It may be used or redistributed in accordance with that license and is released in the hope that it will be useful, but WITHOUT ANY WARRANTY; "
17596 "without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details - "
17597 "you should have received a copy along with this program but if not see <http://www.gnu.org/licenses/>.");
17602 AnsiString ConfigStr =
"";
17603 bool ContinueFlag =
false;
17608 if(ConfigFile.eof())
17614 if(ConfigStr ==
"")
17618 if(ConfigStr[1] ==
'#')
17622 for(
int x = 1; x <= ConfigStr.Length(); x++)
17624 if(ConfigStr[x] ==
'#')
17626 ConfigStr = ConfigStr.SubString(1, x - 1);
17628 while((ConfigStr.SubString(ConfigStr.Length(), 1) == AnsiString(
' ')) || (ConfigStr.SubString(ConfigStr.Length(), 1) == AnsiString(
'\t')))
17630 ConfigStr = ConfigStr.SubString(1, ConfigStr.Length() - 1);
17635 AnsiString ConfigValue = ConfigStr.SubString(9, ConfigStr.Length() - 8);
17636 if((ConfigStr.SubString(1, 8) ==
"Signals=") && FirstLoad)
17639 while((ConfigValue.SubString(1, 1) == AnsiString(
' ')) || (ConfigValue.SubString(1, 1) == AnsiString(
'\t')))
17641 ConfigValue = ConfigValue.SubString(2, ConfigValue.Length() - 1);
17655 SigImagePanel->Caption =
"Signals will be on the right hand side of the track";
17673 SigImagePanel->Caption =
"Signals will be on the left hand side of the track";
17680 if((ConfigStr.SubString(1, 8) ==
"Heatmap=") && FirstLoad)
17683 while((ConfigValue.SubString(1, 1) == AnsiString(
' ')) || (ConfigValue.SubString(1, 1) == AnsiString(
'\t')))
17685 ConfigValue = ConfigValue.SubString(2, ConfigValue.Length() - 1);
17687 if(ConfigValue ==
"redlow")
17694 else if(ConfigValue ==
"redhigh")
17702 if((ConfigStr.SubString(1, 8) ==
"BgndCol=") && FirstLoad)
17706 if(ConfigValue ==
"white")
17710 else if(ConfigValue ==
"blue")
17715 if((ConfigStr.SubString(1, 8) ==
"RLYLocn=") && FirstLoad)
17717 if(DirectoryExists(ConfigValue))
17719 SaveRailwayDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
17720 LoadRailwayDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
17723 else if((ConfigStr.SubString(1, 8) ==
"TTBLocn=") && FirstLoad)
17725 if(DirectoryExists(ConfigValue))
17727 TimetableDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
17728 SaveTTDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
17731 else if((ConfigStr.SubString(1, 8) ==
"SSNLocn=") && FirstLoad)
17733 if(DirectoryExists(ConfigValue))
17735 LoadSessionDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
17738 else if(ConfigStr.SubString(1, 8) ==
"Length =")
17740 for(
int x = 1; x <= ConfigValue.Length(); x++)
17742 if((ConfigValue[x] <
'0') || (ConfigValue[x] >
'9'))
17744 ContinueFlag =
true;
17750 ContinueFlag =
false;
17753 LengthInt = ConfigStr.SubString(9, ConfigStr.Length() - 8).ToInt();
17758 if(LengthInt > 99999)
17767 else if(ConfigStr.SubString(1, 8) ==
"Speed =")
17769 for(
int x = 1; x <= ConfigValue.Length(); x++)
17771 if((ConfigValue[x] <
'0') || (ConfigValue[x] >
'9'))
17773 ContinueFlag =
true;
17779 ContinueFlag =
false;
17782 SpeedInt = ConfigStr.SubString(9, ConfigStr.Length() - 8).ToInt();
17787 else if(SpeedInt > 400)
17802 while(!ConfigFile.eof());
17803 ConfigFile.close();
17807 catch(
const Exception &e)
17809 ShowMessage(
"Unable to load the configuration file, it appears to be corrupt. It will be re-written correctly when the program closes.\n\n"
17810 "Default values will be used for the current session.");
17813 SigImagePanel->Caption =
"Signals will be on the left hand side of the track";
17838 AnsiString ColourStr =
"", SignalStr =
"", LengthStr =
"", SpeedStr =
"", HeatmapColourStr =
"";
17839 remove((
CurDir +
"\\Config.txt").c_str());
17840 std::ofstream ConfigFile((
CurDir +
"\\Config.txt").c_str());
17841 ColourStr =
"black";
17842 SignalStr =
"left";
17855 ColourStr =
"white";
17859 ColourStr =
"blue";
17863 SignalStr =
"right";
17867 HeatmapColourStr =
"redlow";
17871 HeatmapColourStr =
"redhigh";
17873 ConfigFile << AnsiString(
"#This file contains a list of parameters that are saved after each use of the program and reloaded for the "
17874 "next use. Track element length and speed limit values after the = sign may be changed and the configuration file reloaded "
17875 "during play, but please do not change anything else. Comments begin with '#' and are ignored by the program.\n\n");
17876 ConfigFile << AnsiString(
"Signals=") << SignalStr <<
'\n';
17877 ConfigFile << AnsiString(
"BgndCol=") << ColourStr <<
'\n';
17878 ConfigFile << AnsiString(
"RLYLocn=") << AnsiString(
LoadRailwayDialog->InitialDir) <<
'\n';
17879 ConfigFile << AnsiString(
"TTBLocn=") << AnsiString(
TimetableDialog->InitialDir) <<
'\n';
17880 ConfigFile << AnsiString(
"SSNLocn=") << AnsiString(
LoadSessionDialog->InitialDir) <<
'\n';
17881 ConfigFile << AnsiString(
"Heatmap=") << HeatmapColourStr <<
'\n';
17882 ConfigFile << AnsiString(
"Length =") << LengthStr <<
" #default track element length in metres (not less than 10)\n";
17883 ConfigFile << AnsiString(
"Speed =") << SpeedStr <<
" #default track element speed limit in km/h (not less than 10 and not greater than 400)\n";
17884 ConfigFile.close();
17887 catch(
const Exception &e)
17889 ShowMessage(
"Unable to save configuration file, file won't be updated");
17934 int WidthNum = int(
MainScreen->Width / 160) + 1;
17935 int HeightNum = int(
MainScreen->Height / 144) + 1;
17936 for(
int x = 0; x < WidthNum; x++)
17938 for(
int y = 0; y < HeightNum; y++)
18052 int FrontPDPos = -1;
18053 for(
int x = (Route.
PrefDirSize() - 1); x >= 0; x--)
18060 if(FrontPDPos == -1)
18062 throw Exception(
"Failed to find LastTrackVectorPosition in Clearand... for a locked route");
18064 bool BreakFlag =
false;
18175 ZoomButton->Glyph->LoadFromResourceName(0,
"ZoomOut");
18209 InfoPanel->Caption =
"CONNECTING GAPS: Click on connecting element";
18225 UnicodeString MessageStr =
"The railway has changed, close it without saving?";
18226 int button = Application->MessageBox(MessageStr.c_str(), L
"Please confirm", MB_YESNO);
18278 std::ifstream VecFile(FileName);
18280 if(VecFile.is_open())
18300 bool GraphicsFollow =
false;
18301 int NumberOfActiveElements;
18314 if(!(EveryPrefDir->CheckOnePrefDir(0, NumberOfActiveElements, VecFile)))
18345 TDateTime First, Second;
18346 bool Finished =
false;
18348 First = TDateTime::CurrentDateTime();
18349 double TimeVal1 = 86400000 * double(First);
18353 Second = TDateTime::CurrentDateTime();
18354 double TimeVal2 = 86400000 * double(Second);
18355 if((TimeVal2 - TimeVal1) > Msec)
18415 if((LinkNumber1 == 1) || (LinkNumber1 == 3) || (LinkNumber1 == 7) || (LinkNumber1 == 9))
18423 if((LinkNumber2 == 1) || (LinkNumber2 == 3) || (LinkNumber2 == 7) || (LinkNumber2 == 9))
18592 InfoPanel->Caption =
"Select an option from the File, Mode or Help menus";
18760 Screen->Cursor = TCursor(-11);
18768 InfoPanel->Caption =
"PREFERRED DIRECTION SETTING: Select preferred direction start location (right click to erase)";
18775 ShowMessage(
"Preferred direction correctness can be difficult to check by eye\n"
18776 "alone, especially for large railways, so an automated conflict\n"
18777 "check is available in the 'Edit' menu when in preferred\n"
18778 "direction mode.\n\n"
18779 "This message will not be shown again.");
18802 Screen->Cursor = TCursor(-2);
18852 MTBFLabel->Caption =
"Mean time between\ntrain failures in\ntimetable hours";
18865 OperateButton->Glyph->LoadFromResourceName(0,
"RunGraphic");
18896 ShowMessage(
"Performance logfile failed to open, logs won't be saved. Ensure that there is a folder named " +
PERFLOG_DIR_NAME +
18897 " in the folder where the 'Railway.exe' program file resides");
19040 OperateButton->Glyph->LoadFromResourceName(0,
"RunGraphic");
19096 MTBFLabel->Caption =
"Mean time between\ntrain failures in\ntimetable hours";
19105 MTBFLabel->Caption =
"Mean time between\ntrain failures in\ntimetable hours";
19147 InfoPanel->Caption =
"ADDING TRACK: Select element then left click to add it. Right click an element to remove it.";
19186 InfoPanel->Caption =
"ADDING GRAPHIC: Left click layout to add SELECTED graphic, right click to remove ANY graphic.";
19191 InfoPanel->Caption =
"SELECTING USER GRAPHIC: Select the graphic file then add as many as necessary to the layout.";
19195 int HLoc, VLoc, Count;
19197 if(div(Count, 2).rem == 1)
19199 ShowMessage(
"Can't connect, there are an odd number of gaps");
19214 ShowMessage(
"Error - Even number of gaps but all set after first call to HighLightOneGap");
19224 InfoPanel->Caption =
"CONNECTING GAPS: Click on connecting gap";
19231 InfoPanel->Caption =
"ADDING/EDITING TEXT: Left click to add, right click first letter to erase, or left click first letter to edit";
19246 InfoPanel->Caption =
"MOVING TEXT OR GRAPHIC: If text left click first letter, if graphic left click anywhere, then drag";
19253 InfoPanel->Caption =
"NAMING LOCATIONS: Click on location element to add or change name";
19261 InfoPanel->Caption =
"DISTANCE/SPEED SETTING: Select first location (only non-default elements marked)";
19283 InfoPanel->Caption =
"DISTANCE/SPEED SETTING: Select next location";
19287 InfoPanel->Caption =
"DISTANCE/SPEED SETTING: Continue or set values (overall length), or right click to cancel/truncate";
19302 InfoPanel->Caption =
"SELECTING: Select area - click left mouse && drag";
19312 InfoPanel->Caption =
"COPYING: Left click in selection && drag";
19338 bool EraseSuccessfulFlag, NeedToLink =
false, TextChangesMade =
false, GraphicChangesMade =
false;
19339 int ErasedTrackVectorPosition;
19340 Screen->Cursor = TCursor(-11);
19342 InfoPanel->Caption =
"CUT PROCESSING: Please do not click the mouse";
19349 if(EraseSuccessfulFlag)
19351 if(ErasedTrackVectorPosition > -1)
19364 int HighSelectVPos =
SelectRect.bottom * 16;
19370 if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
19378 TextChangesMade =
true;
19388 if((GraphicPtr->HPos >= LowSelectHPos) && ((GraphicPtr->HPos + GraphicPtr->Width) < HighSelectHPos) && (GraphicPtr->VPos >= LowSelectVPos)
19389 && ((GraphicPtr->VPos + GraphicPtr->Height) < HighSelectVPos))
19392 GraphicChangesMade =
true;
19399 Screen->Cursor = TCursor(-2);
19406 InfoPanel->Caption =
"CUTTING: Left click in selection && drag";
19423 if(NeedToLink || TextChangesMade || GraphicChangesMade)
19451 UnicodeString MessageStr =
19452 "Please be aware of the relevant conditions when pasting a railway segment from a different application.\n"
19453 "These are set out in section 3.5 of the manual and " "on-screen help under the heading 'Pasting in an application "
19454 "after cutting or copying from a different application'.\n\n" "This warning will not be shown again.\n\n" "Proceed?";
19455 int button = Application->MessageBox(MessageStr.c_str(), L
"Warning", MB_YESNO | MB_ICONWARNING);
19467 Application->MessageBoxW(L
"Unable to paste (clipboard is invalid) - possibly because another application has changed it)", L
"Warning", MB_OK | MB_ICONWARNING);
19469 TrainController->
LogEvent(
"ValidResult false in case Pasting - probably due to error in RecoverClipboard - see earlier log");
19481 Clipboard()->Clear();
19482 Clipboard()->Close();
19485 bool NeedToLink =
false;
19486 bool TrackLinkingRequiredFlag;
19487 Screen->Cursor = TCursor(-11);
19489 InfoPanel->Caption =
"PASTING: Please wait";
19496 bool TrackEraseSuccessfulFlag;
19497 int ErasedTrackVectorPosition;
19499 for(
int x = LowSelectHLoc; x < HighSelectHLoc; x++)
19501 for(
int y = LowSelectVLoc; y < HighSelectVLoc; y++)
19504 if(ErasedTrackVectorPosition > -1)
19521 if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
19538 if((GraphicPtr->HPos >= LowSelectHPos) && ((GraphicPtr->HPos + GraphicPtr->Width) < HighSelectHPos) && (GraphicPtr->VPos >= LowSelectVPos)
19539 && ((GraphicPtr->VPos + GraphicPtr->Height) < HighSelectVPos))
19553 AnsiString LocName;
19572 int HPos = 0, VPos = 0;
19585 bool InternalChecks =
false;
19589 TrackLinkingRequiredFlag, InternalChecks);
19605 if(TrackLinkingRequiredFlag)
19620 PDVIt->HLoc += HDiff;
19621 PDVIt->VLoc += VDiff;
19626 throw Exception(
"Failed to find TrackVectorPosition in PrefDir setting for Paste");
19628 PDVIt->SetTrackVectorPosition(ATVecPos);
19631 for(
int x = 0; x < 4; x++)
19633 PDVIt->Conn[x] = -1;
19634 PDVIt->ConnLinkPos[x] = -1;
19646 TextPtr->HPos += HDiff * 16;
19647 TextPtr->VPos += VDiff * 16;
19648 AnsiString TempString = TextPtr->TextString;
19664 if(TextPtr->TextString.SubString(1, 4) ==
"##**")
19666 TempString = TextPtr->TextString.SubString(5, TextPtr->TextString.Length());
19669 TextPtr->TextString =
"";
19682 for(TTrack::TUserGraphicVector::iterator GraphicPtr =
Track->
SelectGraphicVector.begin(); GraphicPtr < Track->SelectGraphicVector.end();
19685 GraphicPtr->HPos += HDiff * 16;
19686 GraphicPtr->VPos += VDiff * 16;
19701 Screen->Cursor = TCursor(-2);
19721 UnicodeString MessageStr =
"Selected area will be deleted - proceed?";
19722 int button = Application->MessageBox(MessageStr.c_str(), L
"Please confirm", MB_YESNO);
19727 bool EraseSuccessfulFlag, NeedToLink =
false, TextChangesMade =
false, GraphicChangesMade =
false;
19728 int ErasedTrackVectorPosition;
19729 Screen->Cursor = TCursor(-11);
19731 InfoPanel->Caption =
"DELETING: Please wait";
19738 if(EraseSuccessfulFlag)
19740 if(ErasedTrackVectorPosition > -1)
19752 int HighSelectVPos =
SelectRect.bottom * 16;
19758 AnsiString Check = TextPtr->TextString;
19759 if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
19767 TextChangesMade =
true;
19786 if((GraphicPtr->HPos >= LowSelectHPos) && ((GraphicPtr->HPos + GraphicPtr->Width) < HighSelectHPos) && (GraphicPtr->VPos >= LowSelectVPos)
19787 && ((GraphicPtr->VPos + GraphicPtr->Height) < HighSelectVPos))
19792 if((UserGraphicPtr->HPos == GraphicPtr->HPos) && (UserGraphicPtr->VPos == GraphicPtr->VPos) &&
19793 (UserGraphicPtr->Width == GraphicPtr->Width) && (UserGraphicPtr->Height == GraphicPtr->Height) &&
19794 (UserGraphicPtr->FileName == GraphicPtr->FileName))
19797 GraphicChangesMade =
true;
19817 if(NeedToLink || TextChangesMade || GraphicChangesMade)
19821 Screen->Cursor = TCursor(-2);
19841 catch (
const EClipboardException &e)
19879 bool LeadingPointsAtLastElement =
false;
19882 if(LeadingPointsAtLastElement)
19884 InfoPanel->Caption =
"PREFERRED DIRECTION SETTING: Can't end on leading points, select next location or truncate";
19889 InfoPanel->Caption =
"PREFERRED DIRECTION SETTING: Select next preferred direction location (right click to truncate)";
19894 InfoPanel->Caption =
"PREFERRED DIRECTION SETTING: Add selection or select next location (right click to truncate)";
19909 InfoPanel->Caption =
"SELECTING: Select area - click left mouse && drag";
19954 OperateButton->Glyph->LoadFromResourceName(0,
"PauseGraphic");
20036 if(TTClockTimeChange > 0.000347)
20039 int MinsIncrease = ((TTClockTimeChange * 1440) + 0.5);
20040 int HoursIncrease = 0;
20041 while(MinsIncrease >= 60)
20044 MinsIncrease -= 60;
20046 if(HoursIncrease == 0)
20048 TimeMessage +=
"Timetable clock incremented by " + AnsiString(MinsIncrease) +
"m";
20050 else if(MinsIncrease == 0)
20052 TimeMessage +=
"Timetable clock incremented by " + AnsiString(HoursIncrease) +
"h";
20056 TimeMessage +=
"Timetable clock incremented by " + AnsiString(HoursIncrease) +
"h " + AnsiString(MinsIncrease) +
"m";
20068 MTBFLabel->Caption =
"Mean time between\ntrain failures in\ntimetable hours";
20076 MTBFLabel->Caption =
"Mean time between\ntrain failures in\ntimetable hours";
20085 OperateButton->Glyph->LoadFromResourceName(0,
"RunGraphic");
20115 float LockDelay = 120.0;
20121 bool BreakFlag =
false;
20129 if((TTClockTime - LRVIT->LockStartTime) > TDateTime(LockDelay / 86400))
20132 AnsiString(LRVIT->LastTrackVectorPosition));
20133 while(Route.
LastElementPtr(9)->GetTrackVectorPosition() != LRVIT->RearTrackVectorPosition)
20150 if(Route.
LastElementPtr(17)->GetTrackVectorPosition() == LRVIT->RearTrackVectorPosition)
20195 int TempLockedVectorNumber;
20205 if(((TTClockTime - AutoSigVectorIT->PassoutTime) > TDateTime(AutoSigVectorIT->FirstDelay / 86400)) && (AutoSigVectorIT->AccessNumber == 0))
20207 AutoSigVectorIT->AccessNumber++;
20211 if(((TTClockTime - AutoSigVectorIT->PassoutTime) > TDateTime(AutoSigVectorIT->SecondDelay / 86400)) && (AutoSigVectorIT->AccessNumber == 1))
20213 AutoSigVectorIT->AccessNumber++;
20217 if(((TTClockTime - AutoSigVectorIT->PassoutTime) > TDateTime(AutoSigVectorIT->ThirdDelay / 86400)) && (AutoSigVectorIT->AccessNumber == 2))
20219 AutoSigVectorIT->AccessNumber++;
20228 if(AutoSigVectorIT->AccessNumber > 2)
20243 TPoint MousePoint = Mouse->CursorPos;
20244 int ScreenX = MousePoint.x -
MainScreen->ClientOrigin.x;
20245 int ScreenY = MousePoint.y -
MainScreen->ClientOrigin.y;
20249 ((ScreenX > (
MainScreen->Width - 1)) || (ScreenY > (
MainScreen->Height - 1)) || (ScreenX < 0) || (ScreenY < 0))))
20281 ((MousePoint.y - ClientOrigin.y) >=
TimetableEditPanel->Top) && ((MousePoint.y - ClientOrigin.y) <=
20290 AnsiString TrackFloat =
"", TrainStatusFloat =
"", TrainTTFloat =
"";
20291 bool ShowTrackFloatFlag =
false, ShowTrainStatusFloatFlag =
false, ShowTrainTTFloatFlag =
false;
20301 bool MouseOverOAPanel =
false;
20307 ((MousePoint.y - ClientOrigin.y) >=
ActionsDueForm->Top) && ((MousePoint.y - ClientOrigin.y) <=
20310 MouseOverOAPanel =
true;
20316 bool ActiveTrackFoundFlag =
false, InactiveTrackFoundFlag =
false, TwoTrack =
false;
20317 AnsiString Length01Str =
"", Length23Str =
"", SpeedLimit01Str =
"", SpeedLimit23Str =
"";
20318 AnsiString StationEntryStopLinkPos1Str =
"", StationEntryStopLinkPos2Str =
"";
20319 AnsiString StationEntryStopLinkPos3Str =
"", StationEntryStopLinkPos4Str =
"";
20320 AnsiString ATrackSN =
"", ATrackTN =
"", IATrackSN =
"", LengthAndSpeedCaption =
"";
20321 AnsiString SigAspectString =
"";
20325 if(InactiveTrackFoundFlag)
20330 if(ActiveTrackFoundFlag)
20339 if((ATrackTN !=
"") && (!InactiveTrackFoundFlag || ((InactiveTrackElement.
TrackType !=
Platform) &&
20343 ShowMessage(
"Error - Track has timetable name without corresponding plat/named loc");
20348 ShowMessage(
"Error - plat/named loc and track have different names, or plat/named loc named but not track");
20354 Length01Str = AnsiString(ActiveTrackElement.
Length01);
20355 if(Length01Str ==
"-1")
20357 Length01Str =
"Not Set";
20359 SpeedLimit01Str = AnsiString(ActiveTrackElement.
SpeedLimit01);
20360 if(SpeedLimit01Str ==
"-1")
20362 SpeedLimit01Str =
"Not Set";
20366 Length23Str = AnsiString(ActiveTrackElement.
Length23);
20367 if(Length23Str ==
"-1")
20369 Length23Str =
"Not Set";
20371 SpeedLimit23Str = AnsiString(ActiveTrackElement.
SpeedLimit23);
20372 if(SpeedLimit23Str ==
"-1")
20374 SpeedLimit23Str =
"Not Set";
20378 LengthAndSpeedCaption =
"Straight track length = " + Length01Str +
" m" +
'\n' +
"Diverging track length = " + Length23Str +
" m" +
'\n' +
20379 "Straight track speed limit = " + SpeedLimit01Str +
" km/h" +
'\n' +
"Diverging track speed limit = " + SpeedLimit23Str +
" km/h";
20383 LengthAndSpeedCaption =
"Left diverging track length = " + Length01Str +
" m" +
'\n' +
"Right diverging track length = " + Length23Str +
20384 " m" +
'\n' +
"Left diverging track speed limit = " + SpeedLimit01Str +
" km/h" +
'\n' +
"Right diverging track Speed Limit = " +
20385 SpeedLimit23Str +
" km/h";
20390 if((ActiveTrackElement.
SpeedTag == 15) || (ActiveTrackElement.
SpeedTag == 46))
20392 LengthAndSpeedCaption =
"Horizontal track length = " + Length01Str +
" m" +
'\n' +
"Other track length = " + Length23Str +
" m" +
'\n' +
20393 "Horizontal track speed limit = " + SpeedLimit01Str +
" km/h" +
'\n' +
"Other track speed limit = " + SpeedLimit23Str +
" km/h";
20395 else if(ActiveTrackElement.
SpeedTag == 47)
20397 LengthAndSpeedCaption =
"Horizontal track length = " + Length23Str +
" m" +
'\n' +
"Other track length = " + Length01Str +
" m" +
'\n' +
20398 "Horizontal track speed limit = " + SpeedLimit23Str +
" km/h" +
'\n' +
"Other track speed limit = " + SpeedLimit01Str +
" km/h";
20400 else if(ActiveTrackElement.
SpeedTag == 45)
20402 LengthAndSpeedCaption =
"Vertical track length = " + Length01Str +
" m" +
'\n' +
"Other track length = " + Length23Str +
" m" +
'\n' +
20403 "Vertical track speed limit = " + SpeedLimit01Str +
" km/h" +
'\n' +
"Other track speed limit = " + SpeedLimit23Str +
" km/h";
20405 else if(ActiveTrackElement.
SpeedTag == 44)
20407 LengthAndSpeedCaption =
"Vertical track length = " + Length23Str +
" m" +
'\n' +
"Other track length = " + Length01Str +
" m" +
'\n' +
20408 "Vertical track speed limit = " + SpeedLimit23Str +
" km/h" +
'\n' +
"Other track speed limit = " + SpeedLimit01Str +
" km/h";
20410 else if(ActiveTrackElement.
SpeedTag == 16)
20412 LengthAndSpeedCaption =
"Top left to bottom right track length = " + Length01Str +
" m" +
'\n' +
"Other track length = " + Length23Str +
20413 " m" +
'\n' +
"Top left to bottom right track speed limit = " + SpeedLimit01Str +
" km/h" +
'\n' +
"Other track speed limit = " +
20414 SpeedLimit23Str +
" km/h";
20419 LengthAndSpeedCaption =
"Top track length = " + Length01Str +
" m" +
'\n' +
"Bottom track length = " + Length23Str +
" m" +
'\n' +
20420 "Top track speed limit = " + SpeedLimit01Str +
" km/h" +
'\n' +
"Bottom track speed limit = " + SpeedLimit23Str +
" km/h";
20425 LengthAndSpeedCaption =
"Track length = " + Length01Str +
" m" +
'\n' +
"Track speed limit = " + SpeedLimit01Str +
" km/h";
20428 if(ActiveTrackFoundFlag)
20432 ShowTrackFloatFlag =
true;
20435 TrackFloat =
"Location = " + ATrackTN +
'\n' + LengthAndSpeedCaption +
'\n' +
"ID = " + AnsiString(ActiveTrackElement.
ElementID);
20437 else if(ATrackSN !=
"")
20439 TrackFloat =
"Location = " + ATrackSN +
'\n' + LengthAndSpeedCaption +
'\n' +
"ID = " + AnsiString(ActiveTrackElement.
ElementID);
20441 else if(InactiveTrackFoundFlag)
20443 TrackFloat =
"Location unnamed\n" + LengthAndSpeedCaption +
'\n' +
"ID = " + AnsiString(ActiveTrackElement.
ElementID);
20447 TrackFloat = LengthAndSpeedCaption +
'\n' +
"Track Element ID = " + AnsiString(ActiveTrackElement.
ElementID);
20453 SigAspectString =
"\nThree-aspect signal";
20457 SigAspectString =
"\nTwo-aspect signal";
20461 SigAspectString =
"\nGround signal";
20465 SigAspectString =
"\nFour-aspect signal";
20467 TrackFloat += SigAspectString;
20472 AnsiString RepairTimeStr;
20476 if(ActiveVecPos == FPVIt->TVPos)
20480 RepairTimeStr =
"not yet known.";
20482 else if((FPVIt->RepairTime - Now) <= TDateTime(10.0/1440))
20484 RepairTimeStr =
"only a few minutes.";
20486 else if((FPVIt->RepairTime - Now) <= TDateTime(30.0/1440))
20488 RepairTimeStr =
"30 minutes or less.";
20490 else if((FPVIt->RepairTime - Now) <= TDateTime(60.0/1440))
20492 RepairTimeStr =
"30 minutes to an hour.";
20494 else if((FPVIt->RepairTime - Now) <= TDateTime(120.0/1440))
20496 RepairTimeStr =
"1 to 2 hours.";
20498 else if((FPVIt->RepairTime - Now) > TDateTime(120.0/1440))
20500 RepairTimeStr =
"over 2 hours.";
20505 TrackFloat +=
"\nPoints failed. Repair time " + RepairTimeStr;
20510 AnsiString RepairTimeStr;
20514 if(ActiveVecPos == FPVIt->TVPos)
20518 RepairTimeStr =
"not yet known.";
20520 else if((FPVIt->RepairTime - Now) <= TDateTime(10.0/1440))
20522 RepairTimeStr =
"only a few minutes.";
20524 else if((FPVIt->RepairTime - Now) <= TDateTime(30.0/1440))
20526 RepairTimeStr =
"30 minutes or less.";
20528 else if((FPVIt->RepairTime - Now) <= TDateTime(60.0/1440))
20530 RepairTimeStr =
"30 minutes to an hour.";
20532 else if((FPVIt->RepairTime - Now) <= TDateTime(120.0/1440))
20534 RepairTimeStr =
"1 to 2 hours.";
20536 else if((FPVIt->RepairTime - Now) > TDateTime(120.0/1440))
20538 RepairTimeStr =
"over 2 hours.";
20543 TrackFloat +=
"\nSignal failed. Repair time " + RepairTimeStr;
20548 AnsiString RepairTimeStr;
20552 if(ActiveVecPos == FPVIt->TVPos)
20556 RepairTimeStr =
"not yet known.";
20558 else if((FPVIt->RepairTime - Now) <= TDateTime(10.0/1440))
20560 RepairTimeStr =
"only a few minutes.";
20562 else if((FPVIt->RepairTime - Now) <= TDateTime(30.0/1440))
20564 RepairTimeStr =
"30 minutes or less.";
20566 else if((FPVIt->RepairTime - Now) <= TDateTime(60.0/1440))
20568 RepairTimeStr =
"30 minutes to an hour.";
20570 else if((FPVIt->RepairTime - Now) <= TDateTime(120.0/1440))
20572 RepairTimeStr =
"1 to 2 hours.";
20574 else if((FPVIt->RepairTime - Now) > TDateTime(120.0/1440))
20576 RepairTimeStr =
"over 2 hours.";
20581 TrackFloat +=
"\nTemporary Speed Restriction in place. Restoration time " + RepairTimeStr;
20584 else if(InactiveTrackFoundFlag)
20587 ShowTrackFloatFlag =
true;
20590 if(IATrackSN ==
"")
20592 TrackFloat =
"Location unnamed\nID = " + AnsiString(InactiveTrackElement.
ElementID);
20596 TrackFloat =
"Location = " + IATrackSN +
'\n' +
"ID = " + AnsiString(InactiveTrackElement.
ElementID);
20601 TrackFloat =
"ID = " + AnsiString(InactiveTrackElement.
ElementID);
20607 bool ActionsDueListBoxFloatRequired =
false;
20612 AnsiString FormatOneDPStr =
"####0.0";
20613 AnsiString FormatNoDPStr =
"#######0";
20614 AnsiString MaxBrakeStr =
"";
20615 AnsiString SpecialStr =
"";
20622 int TrainID = -1, ContinuationPos = -1;
20625 ActionsDueListBoxFloatRequired =
true;
20628 ShowTrainStatusFloatFlag =
true;
20632 ShowTrainTTFloatFlag =
true;
20634 if((TrainID > -1) && (ShowTrainStatusFloatFlag || ShowTrainTTFloatFlag))
20640 else if(ContinuationPos > -1)
20647 if(!ActionsDueListBoxFloatRequired)
20650 if(FoundFlag && !MouseOverOAPanel)
20658 ShowTrainStatusFloatFlag =
true;
20663 ShowTrainTTFloatFlag =
true;
20673 TrainStatusFloat =
"No trains expected";
20674 TrainTTFloat =
"No timetable";
20677 ShowTrainStatusFloatFlag =
true;
20681 ShowTrainTTFloatFlag =
true;
20692 AnsiString Caption;
20694 if(!ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
20700 else if(ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
20702 Caption = TrackFloat;
20704 else if(!ShowTrackFloatFlag && ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
20706 Caption = TrainStatusFloat;
20708 else if(ShowTrackFloatFlag && ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
20710 Caption = TrainStatusFloat +
'\n' +
'\n' + TrackFloat;
20712 else if(!ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
20714 if(TrainStatusFloat ==
"No trains expected")
20716 Caption = TrainStatusFloat;
20720 Caption = TrainTTFloat;
20723 else if(ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
20725 if(TrainStatusFloat ==
"No trains expected")
20727 Caption = TrainStatusFloat +
'\n' +
'\n' + TrackFloat;
20731 Caption = TrainTTFloat +
'\n' +
'\n' + TrackFloat;
20734 else if(!ShowTrackFloatFlag && ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
20736 if(TrainStatusFloat ==
"No trains expected")
20738 Caption = TrainStatusFloat;
20742 Caption = TrainStatusFloat +
'\n' +
'\n' + TrainTTFloat;
20745 else if(ShowTrackFloatFlag && ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
20747 if(TrainStatusFloat ==
"No trains expected")
20749 Caption = TrainStatusFloat +
'\n' +
'\n' + TrackFloat;
20753 Caption = TrainStatusFloat +
'\n' +
'\n' + TrainTTFloat +
'\n' +
'\n' + TrackFloat;
20756 int WindowOffsetLeft = 16;
20757 int WindowOffsetRight = 16;
20758 if(ActionsDueListBoxFloatRequired)
20774 WindowOffsetLeft = 96;
20775 WindowOffsetRight = 96;
20781 int Left = ScreenX +
MainScreen->Left + WindowOffsetRight;
20786 Left = ScreenX -
FloatingPanel->Width + 32 - WindowOffsetLeft;
20824 AnsiString &TrainTTFloat)
20833 (CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)))
20840 AnsiString ServiceReferenceInfo =
"";
20844 if(CTEIt->second.RepeatNumber == 0)
20848 ServiceReferenceInfo =
"\nFirst service of ref. " + TTDEPtr->
ServiceReference;
20852 ServiceReferenceInfo =
"\nFirst service";
20857 ServiceReferenceInfo =
"\nRepeat service no. " + AnsiString(CTEIt->second.RepeatNumber);
20861 ServiceReferenceInfo =
"\nRepeat service no. " + AnsiString(CTEIt->second.RepeatNumber) +
" of ref. " + TTDEPtr->
ServiceReference;
20868 ServiceReferenceInfo =
"\nService reference " + TTDEPtr->
ServiceReference;
20873 SpecialStr =
"\nTrain under signaller control";
20875 if(EntrySpeed > LineSpeedLimit)
20877 EntrySpeed = LineSpeedLimit;
20883 if(EntrySpeed > LineSpeedLimit)
20885 EntrySpeed = LineSpeedLimit;
20890 TDateTime TempTime = CTEIt->first;
20892 TrainStatusFloat = CTEIt->second.HeadCode +
": " + CTEIt->second.FixedDescription + ServiceReferenceInfo +
"\nEntry speed " +
20893 AnsiString::FormatFloat(FormatNoDPStr, EntrySpeed) +
"km/h" + SpecialStr +
"\nDelayed, was due at " +
Utilities->
Format96HHMM(TempTime);
20897 TDateTime TempTime = CTEIt->first;
20899 TrainStatusFloat = CTEIt->second.HeadCode +
": " + CTEIt->second.FixedDescription + ServiceReferenceInfo +
"\nEntry speed " +
20900 AnsiString::FormatFloat(FormatNoDPStr, EntrySpeed) +
"km/h" + SpecialStr +
"\nExpected at " +
Utilities->
Format96HHMM(TempTime);
20907 CTEIt->second.IncrementalDigits);
20921 AnsiString HeadCode =
"", ServiceReferenceInfo =
"", Status =
"", CurrSpeedStr =
"", BrakePCStr =
"", NextStopStr =
"", TimeLeftStr =
"",
20922 TimeToNextMovementStr =
"", MassStr =
"", PowerStr =
"";
20923 AnsiString FormatOneDPStr =
"####0.0", MaxBrakeStr =
"", MaxSpeedStr =
"", MaxMPHStr =
"", TrainStatusFloat;
20927 MassStr = AnsiString::FormatFloat(FormatNoDPStr, ((
double)Train.
Mass) / 1000);
20928 PowerStr = AnsiString::FormatFloat(FormatNoDPStr, Train.
PowerAtRail / 1000 / 0.8);
20931 MaxSpeedStr =
"30";
20932 MaxMPHStr =
"19mph";
20936 MaxSpeedStr = AnsiString::FormatFloat(FormatNoDPStr, Train.
MaxRunningSpeed);
20937 MaxMPHStr = AnsiString::FormatFloat(FormatNoDPStr, (Train.
MaxRunningSpeed * 5 / 8)) +
"mph";
20942 TDateTime TimeLeft;
20944 MaxBrakeStr = AnsiString::FormatFloat(FormatNoDPStr, (Train.
MaxBrakeRate * Train.
Mass / 9810));
20956 ServiceReferenceInfo =
"\nFirst service";
20961 ServiceReferenceInfo =
"\nRepeat service no. " + AnsiString(Train.
RepeatNumber);
20979 Status =
"Stopped on signaller's instruction";
20983 Status =
"Not in service";
20987 Status =
"Stopped at buffers";
20991 Status =
"Stopped at signal";
20995 Status =
"Stopped - forward track occupied";
21009 Status =
"Stopped without power - train failed";
21013 Status =
"Stopped without power";
21018 Status =
"Stopped - signal passed at danger";
21022 Status =
"Derailed";
21026 Status =
"Crashed";
21034 Status =
"Accelerating";
21041 if(BrakePCRate < 55)
21043 Status =
"Light braking";
21045 else if(BrakePCRate < 90)
21047 Status =
"Heavy braking";
21051 Status =
"Emergency braking";
21058 if(BrakePCRate < 55)
21060 Status =
"Light braking";
21062 else if(BrakePCRate < 90)
21064 Status =
"Heavy braking";
21068 Status =
"Emergency braking";
21070 CurrSpeed = Train.
EntrySpeed - 3.6 * (Train.
BrakeRate * double(ElapsedDeltaT) * 86400.0);
21075 Status =
"Accelerating";
21081 Status =
"Accelerating";
21083 ((Train.
ExitSpeedFull - Train.
ExitSpeedHalf) * (
double(ElapsedDeltaT - FirstHalfTimeDeltaT) / double(SecondHalfTimeDeltaT)));
21093 Status =
"Coasting - train failed";
21097 Status =
"Coasting - no power";
21102 Status =
"Constant speed";
21113 Status =
"Coasting - train failed";
21117 Status =
"Coasting - no power";
21122 Status =
"Constant speed";
21129 NextStopStr =
"At signaller's discretion";
21133 NextStopStr =
"None";
21142 SpecialStr =
"Train under signaller control" + AnsiString(
'\n');
21146 SpecialStr =
"Restricted speed - being called on" + AnsiString(
'\n');
21149 if(RemTimeHalf < 0)
21154 if(RemTimeFull < 0)
21158 if(RemTimeHalf > 0)
21160 TimeLeft = RemTimeHalf;
21164 TimeLeft = RemTimeFull;
21166 TimeToNextMovementStr =
"Time to next movement (sec) = " + TimeLeftStr.FormatFloat(FormatOneDPStr,
double(TimeLeft));
21168 AnsiString OverallDelayString = AnsiString(
'\n');
21173 OverallDelayString = AnsiString(
"\nTotal random delay ") + AnsiString(
int(Train.
DelayedRandMins)) + AnsiString(
" minutes\n");
21177 OverallDelayString = AnsiString(
"\nTotal random delay 1 minute\n");
21182 TimeToNextMovementStr =
"";
21189 TrainStatusFloat = HeadCode +
": " + Train.
Description + ServiceReferenceInfo +
'\n' +
"Maximum train speed " + MaxSpeedStr +
21190 "km/h (" + MaxMPHStr +
"); Power " + PowerStr +
"kW" +
'\n' +
"Mass " + MassStr +
"Te; Brakes " + MaxBrakeStr +
"Te" +
'\n' + SpecialStr + Status +
'\n' +
21191 "New random delay here of 1 minute" + OverallDelayString + AnsiString(
"\nNext: ") + NextStopStr;
21195 TrainStatusFloat = HeadCode +
": " + Train.
Description + ServiceReferenceInfo +
'\n' +
"Maximum train speed " + MaxSpeedStr +
21196 "km/h (" + MaxMPHStr +
"); Power " + PowerStr +
"kW" +
'\n' +
"Mass " + MassStr +
"Te; Brakes " + MaxBrakeStr +
"Te" +
'\n' + SpecialStr + Status +
'\n' +
21197 "New random delay here of " + AnsiString(
int(Train.
NewDelay)) +
" minutes" + OverallDelayString + AnsiString(
"\nNext: ") + NextStopStr;
21201 TrainStatusFloat = HeadCode +
": " + Train.
Description + ServiceReferenceInfo +
'\n' +
"Maximum train speed " + MaxSpeedStr +
21202 "km/h (" + MaxMPHStr +
"); Power " + PowerStr +
"kW" +
'\n' +
"Mass " + MassStr +
"Te; Brakes " + MaxBrakeStr +
"Te" +
'\n' + SpecialStr + Status +
21203 OverallDelayString + AnsiString(
"\nNext: ") + NextStopStr;
21208 TrainStatusFloat = HeadCode +
": " + Train.
Description + ServiceReferenceInfo +
'\n' +
"Maximum train speed " + MaxSpeedStr +
21209 "km/h (" + MaxMPHStr +
"); Power " + PowerStr +
"kW" +
'\n' +
"Mass " + MassStr +
"Te; Brakes " + MaxBrakeStr +
"Te" +
'\n' + SpecialStr + Status +
21210 OverallDelayString + AnsiString(
"\nNext: ") + NextStopStr;
21214 TrainStatusFloat = HeadCode +
": " + Train.
Description + ServiceReferenceInfo +
'\n' +
"Maximum train speed " + MaxSpeedStr +
21215 "km/h (" + MaxMPHStr +
"); Power " + PowerStr +
"kW" +
'\n' +
"Mass " + MassStr +
"Te; Brakes " + MaxBrakeStr +
"Te" +
'\n' + SpecialStr + Status +
": " +
21216 CurrSpeedStr.FormatFloat(FormatNoDPStr, CurrSpeed) +
"km/h (" + CurrSpeedStr.FormatFloat(FormatNoDPStr, (CurrSpeed * 5 / 8)) +
"mph)" +
21217 OverallDelayString + AnsiString(
"\nNext: ") + NextStopStr;
21220 return(TrainStatusFloat);
21351 InfoPanel->Caption =
"PRE-START: Route setting in progress";
21355 InfoPanel->Caption =
"OPERATING: Route setting in progress";
21494 bool Manual =
false;
21543 throw Exception(
"Failed to find a route at LC position HLoc = " + (AnsiString)H +
" VLoc = " + (AnsiString)V);
21548 if(RouteNumber > -1)
21582 bool SaveRailwayButtonsFlag =
true;
21591 SaveRailwayButtonsFlag =
false;
21609 SaveRailwayButtonsFlag =
false;
21617 SaveRailwayButtonsFlag =
false;
21671 bool ZoomFlag =
true, HomeFlag =
true, NewHomeFlag =
true, ScreenLeftFlag =
true, ScreenRightFlag =
true, ScreenUpFlag =
true, ScreenDownFlag =
true,
21672 TrackBuildPanelEnabledFlag =
true, PrefDirPanelEnabledFlag =
true, OperatingPanelEnabledFlag =
true, TimetablePanelEnabledFlag =
true;
21674 AnsiString TrackBuildPanelLabelCaptionStr =
"Build/modify";
21675 AnsiString PrefDirPanelLabelCaptionStr =
"Preferred direction selection";
21676 AnsiString OperatingPanelLabelCaptionStr =
"Operation";
21677 AnsiString TimetablePanelLabelCaptionStr =
"Timetable editor";
21684 ScreenLeftFlag =
false;
21688 ScreenRightFlag =
false;
21692 ScreenUpFlag =
false;
21696 ScreenDownFlag =
false;
21704 ScreenLeftFlag =
false;
21708 ScreenRightFlag =
false;
21712 ScreenUpFlag =
false;
21716 ScreenDownFlag =
false;
21723 NewHomeFlag =
false;
21724 ScreenLeftFlag =
false;
21725 ScreenRightFlag =
false;
21726 ScreenUpFlag =
false;
21727 ScreenDownFlag =
false;
21732 TrackBuildPanelEnabledFlag =
false;
21733 TrackBuildPanelLabelCaptionStr =
"Disabled";
21734 PrefDirPanelEnabledFlag =
false;
21735 PrefDirPanelLabelCaptionStr =
"Disabled";
21736 OperatingPanelEnabledFlag =
false;
21737 OperatingPanelLabelCaptionStr =
"Disabled";
21738 TimetablePanelEnabledFlag =
false;
21739 TimetablePanelLabelCaptionStr =
"Disabled";
21749 OperatingPanelEnabledFlag =
false;
21750 OperatingPanelLabelCaptionStr =
"Disabled";
21753 NewHomeFlag =
false;
21754 ScreenLeftFlag =
false;
21755 ScreenRightFlag =
false;
21756 ScreenUpFlag =
false;
21757 ScreenDownFlag =
false;
21770 NewHomeFlag =
false;
21771 ScreenLeftFlag =
false;
21772 ScreenRightFlag =
false;
21773 ScreenUpFlag =
false;
21774 ScreenDownFlag =
false;
21780 NewHomeFlag =
false;
21781 ScreenLeftFlag =
false;
21782 ScreenRightFlag =
false;
21783 ScreenUpFlag =
false;
21784 ScreenDownFlag =
false;
21791 NewHomeFlag =
false;
21792 ScreenLeftFlag =
false;
21793 ScreenRightFlag =
false;
21794 ScreenUpFlag =
false;
21795 ScreenDownFlag =
false;
21834 if(ScreenRightFlag)
21858 if(OperatingPanelEnabledFlag)
21866 if(TrackBuildPanelEnabledFlag)
21874 if(PrefDirPanelEnabledFlag)
21882 if(TimetablePanelEnabledFlag)
21905 bool CallOnValid =
false;
21911 CallOnValid =
true;
22003 Screen->Cursor = TCursor(-2);
22073 Caption =
"Railway: New railway under development";
22077 Caption =
"Railway: " +
RailwayTitle +
" under development";
22172 TFont *TempFont =
new TFont;
22174 TempFont->Style.Clear();
22175 TempFont->Name =
"MS Sans Serif";
22176 TempFont->Size = 10;
22178 TempFont->Charset = (TFontCharset)(0);
22283 if(NonPrefDirChangesMade)
22309 AnsiString CurrentDateTimeStr =
"", TimetableTimeStr =
"", SessionFileStr =
"";
22310 Screen->Cursor = TCursor(-11);
22311 CurrentDateTimeStr = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
22314 TimetableTimeStr = TimetableTimeStr.SubString(1, 2) +
'.' + TimetableTimeStr.SubString(4, 2) +
'.' + TimetableTimeStr.SubString(7, 2);
22315 SessionFileStr =
LoadSessionDialog->InitialDir +
"\\Session " + CurrentDateTimeStr +
"; Timetable time " + TimetableTimeStr +
"; " +
RailwayTitle +
22317 std::ofstream SessionFile(SessionFileStr.c_str());
22318 if(SessionFile.fail())
22321 "has been deleted or its name changed?\n\n"
22322 "Will attempt to save in the folder where\n"
22323 "'railway.exe' resides (can move to a more\n"
22324 "appropriate folder manually later).\n");
22325 SessionFile.clear();
22326 SessionFileStr =
CurDir +
"\\Session " + CurrentDateTimeStr +
"; Timetable time " + TimetableTimeStr +
"; " +
RailwayTitle +
22329 SessionFile.open(SessionFileStr.c_str());
22331 if(!(SessionFile.fail()))
22373 SessionFile.close();
22374 DeleteFile(SessionFileStr);
22375 Screen->Cursor = TCursor(-2);
22557 AnsiString ReminderEntry =
"";
22564 for(
unsigned int y = 0; y < AV.size(); y++)
22566 if(AV.at(y).Reminder > 0)
22568 ReminderEntry = AnsiString(x + (10000 * AV.at(y).Reminder)) +
'-' + AnsiString(y);
22589 TTrain TempTrain = *TVIt;
22646 SessionFile.close();
22657 Screen->Cursor = TCursor(-2);
22660 catch(
const Exception &e)
22663 Screen->Cursor = TCursor(-2);
22695 Screen->Cursor = TCursor(-11);
22700 if(!(SessionFile.fail()))
22711 int LastCharBeforeFloat = TempString.LastDelimiter(
'*');
22712 if((LastCharBeforeFloat == 0) || (LastCharBeforeFloat == TempString.Length()))
22719 AnsiString FloatStr = TempString.SubString(LastCharBeforeFloat + 1, TempString.Length() - LastCharBeforeFloat);
22735 bool GraphicsFollow =
false;
22741 SessionFile.close();
22742 Screen->Cursor = TCursor(-2);
22743 ShowMessage(
"Track not linked, session can't be loaded");
22759 SessionFile.close();
22760 Screen->Cursor = TCursor(-2);
22761 ShowMessage(
"Corruption in preferred direction section of the session file, session can't be loaded");
22769 SessionFile.close();
22770 Screen->Cursor = TCursor(-2);
22771 ShowMessage(
"Corruption in route section of the session file, session can't be loaded");
22783 if(TempString ==
"***BarriersDownVector***")
22791 SessionFile.close();
22792 Screen->Cursor = TCursor(-2);
22793 ShowMessage(
"Unable to load timetable section of the session file, session can't be loaded");
22800 SessionFile.close();
22801 Screen->Cursor = TCursor(-2);
22802 throw Exception(
"TimetableTitle null in LoadSession");
22824 ShowMessage(
"Performance logfile failed to open, logs won't be saved. Ensure that there is a folder named " +
PERFLOG_DIR_NAME +
22825 " in the folder where the 'Railway.exe' program file resides");
22832 SessionFile.get(TempChar);
22833 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
22835 SessionFile.get(TempChar);
22837 if(SessionFile.eof())
22841 SessionFile.close();
22842 goto FINISHEDLOADING;
22852 double PowerDouble;
22864 SessionFile.get(TempChar);
22865 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
22867 SessionFile.get(TempChar);
22869 if(SessionFile.eof())
22871 SessionFile.close();
22872 goto FINISHEDLOADING;
22874 if((TempChar !=
'0') && (TempChar !=
'1'))
22876 throw Exception(
"TempChar value = " + AnsiString(TempChar) +
", should be 0 or 1");
22879 if(TempChar ==
'0')
22887 SessionFile.get(TempChar);
22888 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
22890 SessionFile.get(TempChar);
22892 if(SessionFile.eof())
22899 SessionFile.close();
22900 goto FINISHEDLOADING;
22903 TempString = TempChar;
22904 SessionFile.get(TempChar);
22905 while((TempChar !=
'\n') && (TempChar !=
'\0'))
22907 TempString = TempString + TempChar;
22908 SessionFile.get(TempChar);
22919 SessionFile.get(TempChar);
22920 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
22922 SessionFile.get(TempChar);
22924 if(SessionFile.eof())
22927 SessionFile.close();
22928 goto FINISHEDLOADING;
22931 TempString = TempChar;
22932 SessionFile.get(TempChar);
22933 while((TempChar !=
'\n') && (TempChar !=
'\0'))
22935 TempString = TempString + TempChar;
22936 SessionFile.get(TempChar);
22941 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
22943 SessionFile.get(TempChar);
22945 if(SessionFile.eof())
22947 SessionFile.close();
22948 goto FINISHEDLOADING;
22951 TempString = TempChar;
22952 while(TempString !=
'E')
22954 SessionFile.get(TempChar);
22955 while((TempChar !=
'\n') && (TempChar !=
'\0'))
22957 TempString = TempString + TempChar;
22958 SessionFile.get(TempChar);
22966 SessionFile.get(TempChar);
22967 TempString = TempChar;
22968 while((TempChar ==
'\n') || (TempChar ==
'\0'))
22970 SessionFile.get(TempChar);
22971 TempString = TempChar;
22978 SessionFile.get(TempChar);
22979 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
22981 SessionFile.get(TempChar);
22983 if(SessionFile.eof())
22985 SessionFile.close();
22986 goto FINISHEDLOADING;
22989 TempString = TempChar;
22990 while(TempString !=
'E')
22992 SessionFile.get(TempChar);
22993 while((TempChar !=
'\n') && (TempChar !=
'\0'))
22995 TempString = TempString + TempChar;
22996 SessionFile.get(TempChar);
23001 SessionFile.get(TempChar);
23002 TempString = TempChar;
23003 while((TempChar ==
'\n') || (TempChar ==
'\0'))
23005 SessionFile.get(TempChar);
23006 TempString = TempChar;
23013 SessionFile.get(TempChar);
23014 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
23016 SessionFile.get(TempChar);
23018 if(SessionFile.eof())
23021 SessionFile.close();
23022 goto FINISHEDLOADING;
23026 while((TempChar !=
'\n') && (TempChar !=
'\0'))
23028 TempString = TempString + TempChar;
23029 SessionFile.get(TempChar);
23044 int TempInt, VecSize;
23048 for(
int x = 0; x < VecSize; x++)
23053 FPVE.
TVPos = TempInt;
23066 for(
int x = 0; x < VecSize; x++)
23071 FPVE.
TVPos = TempInt;
23080 for(
int x = 0; x < VecSize; x++)
23085 FPVE.
TVPos = TempInt;
23098 SessionFile.get(TempChar);
23099 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
23101 SessionFile.get(TempChar);
23103 if(SessionFile.eof())
23123 SessionFile.close();
23124 goto FINISHEDLOADING;
23127 if(TempChar ==
'0')
23137 else if(TempChar ==
'1')
23147 else if(TempChar ==
'2')
23153 DelayMenu->Caption =
"Moderate delays";
23157 else if(TempChar ==
'3')
23169 throw Exception(
"Session file DelayMode not in range");
23171 SessionFile.get(TempChar);
23172 SessionFile.get(TempChar);
23173 if(TempChar ==
'0')
23186 else if(TempChar ==
'1')
23199 else if(TempChar ==
'2')
23212 else if(TempChar ==
'3')
23227 throw Exception(
"Session file FailureMode not in range");
23229 SessionFile.get(TempChar);
23234 SessionFile.get(TempChar);
23235 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
23237 SessionFile.get(TempChar);
23239 if(SessionFile.eof())
23241 SessionFile.close();
23242 goto FINISHEDLOADING;
23246 while((TempChar !=
'\n') && (TempChar !=
'\0'))
23248 TempString = TempString + TempChar;
23249 SessionFile.get(TempChar);
23252 if(TempString ==
"End of file at v2.16.1")
23265 TVIt->Description = TempString;
23278 SessionFile.get(TempChar);
23279 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
23281 SessionFile.get(TempChar);
23283 if(SessionFile.eof())
23286 SessionFile.close();
23287 goto FINISHEDLOADING;
23289 AnsiString ReminderEntry =
"";
23292 while((TempChar !=
'\n') && (TempChar !=
'\0'))
23294 TempString = TempString + TempChar;
23295 SessionFile.get(TempChar);
23298 while(TempString !=
"End of file at v2.19.0")
23300 int PosDash = TempString.Pos(
'-');
23307 AnsiString x = TempString.SubString(1, PosDash - 1);
23309 unsigned int TrainVecPos = x.SubString(2, 4).ToInt();
23310 unsigned int Reminder = x.SubString(1, 1).ToInt();
23311 unsigned int y = TempString.SubString(PosDash + 1, TempString.Length() - PosDash).ToInt();
23314 AV.at(y).Reminder = Reminder;
23321 SessionFile.get(TempChar);
23322 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
23324 SessionFile.get(TempChar);
23326 if(SessionFile.eof())
23329 SessionFile.close();
23330 goto FINISHEDLOADING;
23338 TVIt->AllowedToPassRedSignal = TempChar;
23350 SessionFile.get(TempChar);
23351 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
23353 SessionFile.get(TempChar);
23355 if(SessionFile.eof())
23358 SessionFile.close();
23359 goto FINISHEDLOADING;
23363 if((TempChar ==
'0') || (TempChar ==
'1'))
23370 TVIt->RemainHereLogNotSent =
true;
23371 if(TempChar ==
'0')
23373 TVIt->RemainHereLogNotSent =
false;
23406 TVIt->MinsDelayed = (float)MD;
23407 TVIt->OpTimeToAct = (float)OTTA;
23408 TVIt->TimeToExit = (float)TTE;
23409 TVIt->FirstLaterStopRecoverableTime = (float)FLSRT;
23412 TVIt->UpdateCounter = (
unsigned int)UD;
23415 TVIt->ExitPair.first = EP1;
23416 TVIt->ExitPair.second = EP2;
23432 SessionFile.get(TempChar);
23433 while(!SessionFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
23435 SessionFile.get(TempChar);
23437 if(SessionFile.eof())
23443 TVIt->NonDefaultMinDwellTimeFlag =
false;
23444 TVIt->ArrivalMinDwellTime = 30.0;
23447 SessionFile.close();
23448 goto FINISHEDLOADING;
23456 TVIt->NonDefaultMinDwellTimeFlag = (TempChar ==
'1');
23463 if(!TVIt->NonDefaultMinDwellTimeFlag)
23465 TVIt->ArrivalMinDwellTime = 30.0;
23477 if(SessionFile.is_open())
23479 SessionFile.close();
23487 if(TVIt->Description ==
"")
23489 TVIt->Description = TVIt->TrainDataEntryPtr->FixedDescription;
23531 for(
int y = 0; y < 4; y++)
23545 ARVIt->SetRouteSignals(13);
23549 for(TTrainController::TTrainVector::iterator TVIt =
TrainController->
TrainVector.begin(); TVIt < TrainController->TrainVector.end(); TVIt++)
23575 ShowMessage(
"Session file integrity check failed, unable to load " +
LoadSessionDialog->FileName +
23576 ".\n\nPlease make sure that the timetable has been validated and that you are using the latest program version.");
23578 Screen->Cursor = TCursor(-2);
23582 catch(
const Exception &e)
23584 if((e.Message.Pos(
"esource") > 0) || (e.Message.Pos(
"arameter") > 0))
23586 Screen->Cursor = TCursor(-2);
23597 UnicodeString MessageStr =
23598 "Insufficient memory available to load the file, and partial load likely to be corrupt. Application will terminate. Try loading the session as the first action after reloading the program.";
23600 Application->MessageBox(MessageStr.c_str(), L
"Out of memory", MB_OK | MB_ICONERROR);
23601 Application->Terminate();
23605 TrainController->
StopTTClockMessage(96,
"Session file failed to load - is the latest program version in use?\nIf so then the file may be corrupt.\n\nError message: " + e.Message);
23606 Screen->Cursor = TCursor(-2);
23680 if(OpMode ==
"PreStart")
23743 AnsiString OpMode =
"";
23750 else if((OpMode !=
"PreStart") && (OpMode !=
"NotPreStart"))
23979 SessionFile.close();
23980 SessionFile.open(SessionFileStr.c_str(), std::ios_base::app | std::ios_base::binary);
23994 ShowMessage(
"Failed to open temporary timetable file. Unable to save the session");
24000 char *Buffer =
new char[10000];
24005 BytesRead = FileRead(Handle, Buffer, 10000);
24006 SessionFile.write(Buffer, BytesRead);
24007 if(BytesRead < 10000)
24015 SessionFile.close();
24016 SessionFile.open(SessionFileStr.c_str(), std::ios_base::app | std::ios_base::out);
24040 if(!FileExists(TimetableFileName))
24046 ErrorFile.open(ErrorFileStr.c_str(), std::ios_base::app | std::ios_base::binary);
24048 int Handle = FileOpen(TimetableFileName, fmOpenRead);
24055 Handle = FileOpen(TimetableFileName, fmOpenRead);
24065 char *Buffer =
new char[10000];
24070 BytesRead = FileRead(Handle, Buffer, 10000);
24071 ErrorFile.write(Buffer, BytesRead);
24072 if(BytesRead < 10000)
24081 ErrorFile.open(ErrorFileStr.c_str(), std::ios_base::app | std::ios_base::out);
24109 int TempTTFileNumber = 0;
24111 while(FileExists(
CurDir +
"\\TmpTT" + AnsiString(TempTTFileNumber) +
".tmp"))
24113 TempTTFileNumber++;
24121 if(!TTBFile.fail())
24123 char *Buffer =
new char[10000];
24124 char TempChar = (char)(SessionFile.peek());
24125 if(TempChar ==
'\n')
24127 SessionFile.get(TempChar);
24129 if(!SessionFile.getline(Buffer, 10000,
'\0'))
24138 for(
int x = 0; x < 10000; x++)
24140 if(Buffer[x] !=
'\0')
24149 while(AnsiString(Buffer) !=
"***End***")
24151 TTBFile.write(Buffer, Count);
24152 TTBFile.write(&Zero, 1);
24154 if(!SessionFile.getline(Buffer, 10000,
'\0'))
24163 for(
int x = 0; x < 10000; x++)
24165 if(Buffer[x] !=
'\0')
24179 bool GiveMessagesFalse =
false;
24180 bool CheckLocationsExistInRailwayTrue =
true;
24183 std::ifstream TTBLFile(
TempTTFileName.c_str(), std::ios_base::binary);
24184 if(TTBLFile.is_open())
24186 bool SessionFileTrue =
true;
24217 for(
int x = 0; x < NumberOfTrainEntries; x++)
24225 for(
int y = 0; y < NumberOfTrains; y++)
24250 AnsiString OutString;
24257 while(OutString !=
"***End***")
24266 if(SessionFile.fail())
24271 int NumberOfTrainEntries;
24278 for(
int x = 0; x < NumberOfTrainEntries; x++)
24280 int NumberOfTrains;
24286 for(
int y = 0; y < NumberOfTrains; y++)
24317 bool EndOfFile =
false;
24319 char *TrainTimetableString =
new char[10000];
24323 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
24324 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
24331 AnsiString OneLine(TrainTimetableString);
24332 bool FinalCallTrue =
true;
24334 CheckLocationsExistInRailway))
24336 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
24337 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
24340 throw Exception(
"Timetable FinalCall error - no start time on own line, Count = 0");
24342 OneLine = AnsiString(TrainTimetableString);
24348 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
24349 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
24356 OneLine = AnsiString(TrainTimetableString);
24362 throw Exception(
"Timetable FinalCall error in processing one timetable line, Count = " + AnsiString(Count));
24364 if(EndOfFile && (Count < 2))
24367 throw Exception(
"Timetable FinalCall error - too few or no relevant entries, Count = " + AnsiString(Count));
24372 delete[]TrainTimetableString;
24373 bool TwoLocationFlag;
24381 ShowMessage(
"Timetable secondary integrity check failed - unable to load.\n\nPlease make sure that the timetable has been validated and that you are using the latest program version.");
24418 bool EndOfFile =
false;
24420 char *TrainTimetableString =
new char[10000];
24424 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
24425 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
24432 AnsiString OneLine(TrainTimetableString);
24433 bool FinalCallTrue =
true;
24435 CheckLocationsExistInRailway))
24437 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
24438 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
24441 throw Exception(
"Timetable FinalCall error - no start time on own line, Count = 0");
24443 OneLine = AnsiString(TrainTimetableString);
24449 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
24450 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
24457 OneLine = AnsiString(TrainTimetableString);
24463 throw Exception(
"Timetable FinalCall error in processing one timetable line, Count = " + AnsiString(Count));
24465 if(EndOfFile && (Count < 2))
24468 throw Exception(
"Timetable FinalCall error - too few or no relevant entries, Count = " + AnsiString(Count));
24473 delete[]TrainTimetableString;
24474 bool TwoLocationFlag;
24485 else if(TwoLocationFlag)
24487 AnsiString AllServices =
"", Suffix =
"";
24497 AllServices = AllServices + *TLLIt +
", ";
24503 Suffix =
"(more than 5, first 5 are) ";
24507 TwoLocationNameLabel->Caption =
"The following services have two or more locations with the same name without a change of\n"
24508 "direction between them. If this isn't intended then please correct them.\n\n"
24509 "Before ticking the check box please be sure that all services are correct.\n\n"
24510 "Services: " + Suffix +
" " + AllServices;
24514 TwoLocationNameLabel->Caption =
"The following service has two or more locations with the same name without a change of\n"
24515 "direction between them. If this isn't intended then please correct it.\n\n"
24516 "Service: " + AllServices;
24546 std::ifstream InFile(FileName.c_str());
24548 int NumberOfActiveElements;
24549 bool GraphicsFollow =
false;
24551 if(InFile.is_open())
24698 if((TempString !=
"***BarriersDownVector***") && (TempString !=
"***Timetable***"))
24704 if(TempString ==
"***BarriersDownVector***")
24748 InFile.open(FileName.c_str());
24749 if(InFile.is_open())
24770 bool GraphicsFollow =
false;
24891 if((TempString !=
"***BarriersDownVector***") && (TempString !=
"***Timetable***"))
24897 if(TempString ==
"***BarriersDownVector***")
24976 InFile.get(TempChar);
24977 while(!InFile.eof() && ((TempChar ==
'\n') || (TempChar ==
'\0')))
24979 InFile.get(TempChar);
25010 double PowerDouble;
25040 AnsiString TempString =
"", Line1 =
"", Line2 =
"", Line3 =
"", Line4 =
"", Line5 =
"";
25041 char *Buffer =
new char[1000];
25044 InFile.get(TempChar);
25045 InFile.getline(Buffer, 1000);
25046 TempString = AnsiString(Buffer);
25047 if(TempString ==
"***End of performance file***")
25054 while(TempString !=
"***End of performance file***")
25059 InFile.getline(Buffer, 1000);
25060 TempString = AnsiString(Buffer);
25072 AnsiString TempString =
"";
25075 InFile.get(TempChar);
25076 if(TempChar !=
'\n')
25086 while(TempString !=
"***End of performance file***")
25107 AnsiString OneLine = Text.SubString(1, Text.Pos(
'\x0D'));
25108 while((OneLine.Length() > 0) && OneLine[OneLine.Length()] <
' ')
25110 OneLine.SetLength(OneLine.Length() - 1);
25112 Text = Text.SubString(Text.Pos(
'\x0D'), Text.Length());
25113 while((Text.Length() > 0) && Text[1] <
' ')
25115 Text = Text.SubString(2, (Text.Length() - 1));
25117 OutFile << OneLine.c_str() <<
'\n';
25139 InfoPanel->Caption =
"PRE-START: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
25143 InfoPanel->Caption =
"OPERATING: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
25157 InfoPanel->Caption =
"PRE-START: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
25161 InfoPanel->Caption =
"OPERATING: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
25175 InfoPanel->Caption =
"PRE-START: Select PREFERRED ROUTE start signal, or left click points to change manually";
25179 InfoPanel->Caption =
"OPERATING: Select PREFERRED ROUTE start signal, or left click points to change manually";
25193 InfoPanel->Caption =
"PRE-START: Select PREFERRED ROUTE start signal, or left click points to change manually";
25197 InfoPanel->Caption =
"OPERATING: Select PREFERRED ROUTE start signal, or left click points to change manually";
25211 InfoPanel->Caption =
"PRE-START: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
25215 InfoPanel->Caption =
"OPERATING: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
25230 InfoPanel->Caption =
"PRE-START: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
25234 InfoPanel->Caption =
"OPERATING: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
25261 InfoPanel->Caption =
"Left click screen to zoom in at that position";
25266 InfoPanel->Caption =
"PAUSED: Railway state changes disabled";
25346 Screen->Cursor = TCursor(-11);
25347 AnsiString ErrorFileStr =
CurDir +
"\\errorlog.err";
25348 std::ofstream ErrorFile(ErrorFileStr.c_str());
25350 if(!(ErrorFile.fail()))
25353 int ScreenX = Mouse->CursorPos.x -
MainScreen->ClientOrigin.x;
25354 int ScreenY = Mouse->CursorPos.y -
MainScreen->ClientOrigin.y;
25355 AnsiString MouseStr =
"Posx: " + AnsiString(ScreenX) +
"; Posy: " + AnsiString(ScreenY);
25362 ErrorFile << Item.c_str() <<
'\n';
25369 ErrorFile << Item.c_str() <<
'\n';
25613 AnsiString ReminderEntry =
"";
25620 for(
unsigned int y = 0; y < AV.size(); y++)
25622 if(AV.at(y).Reminder > 0)
25624 ReminderEntry = AnsiString(x + (10000 * AV.at(y).Reminder)) +
'-' + AnsiString(y);
25644 TTrain TempTrain = *TVIt;
25715 Screen->Cursor = TCursor(-2);
25732 int TempTTFileNumber = 0;
25734 while(FileExists(
CurDir +
"\\TmpTT" + AnsiString(TempTTFileNumber) +
".tmp"))
25736 TempTTFileNumber++;
25739 int InHandle = FileOpen(InFileName, fmOpenRead);
25742 while(InHandle < 0)
25744 InHandle = FileOpen(InFileName, fmOpenRead);
25749 ShowMessage(
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
25757 while(OutHandle < 0)
25764 ShowMessage(
"Failed to save temporary timetable file, sessions can't be saved - try again, may only be a temporary problem");
25765 FileClose(InHandle);
25770 int CountIn, CountOut;
25771 char *Buffer =
new char[10000];
25775 CountIn = FileRead(InHandle, Buffer, 10000);
25776 CountOut = FileWrite(OutHandle, Buffer, CountIn);
25777 if(CountOut != CountIn)
25779 ShowMessage(
"Error in writing to the temporary timetable file, sessions can't be saved - try again, may only be a temporary problem");
25781 FileClose(InHandle);
25782 FileClose(OutHandle);
25786 if(CountIn < 10000)
25792 FileClose(InHandle);
25793 FileClose(OutHandle);
25838 int VarElements = 0;
25839 bool NamedLocPresent =
false;
25847 throw Exception(
"Error - failed to find track element at " + AnsiString(TE.
HLoc) +
" & " + AnsiString(TE.
VLoc) +
" in SetLengths");
25856 NamedLocPresent =
true;
25861 if(SpeedLimit != -1)
25868 if(SpeedLimit != -1)
25879 if((NamedLocPresent) && (VarElements > 0) && ((Distance / VarElements) < 50))
25883 ShowMessage(
"Note: Named location elements are quite short. If they are too short the simulation might be too unrealistic.\n\nThis message will not be shown again.");
25887 if((NamedLocPresent) && (VarElements > 0) && ((Distance / VarElements) > 200))
25891 ShowMessage(
"Note: Named location elements are quite long. If they are too long the simulation might be too unrealistic.\n\nThis message will not be shown again.");
25895 if((VarElements * 10) > Distance)
25897 ShowMessage(
"Required distance is less than the minimum, will set each element to the minimum (10m)");
25898 Distance = (VarElements * 10);
25900 if(VarElements == 0)
25903 ShowMessage(
"No elements selected");
25908 int RemainingDistance = Distance, RemainingVarElements = VarElements, NextLength = RemainingDistance / VarElements;
25916 if(NextLength < 10)
25942 RemainingDistance -= NextLength;
25943 RemainingVarElements--;
25944 if(RemainingVarElements > 0)
25946 NextLength = RemainingDistance / RemainingVarElements;
25974 ShowMessage(
"Nothing to save!");
25980 SaveRailwayDialog->Filter =
"Development file (*.dev)|*.dev|Railway file (*.rly)|*.rly";
25993 Screen->Cursor = TCursor(-11);
25995 AnsiString Extension =
"";
26003 if(!(VecFile.fail()))
26031 if((LastChar ==
'y') || (LastChar ==
'Y'))
26060 ShowMessage(
"File open failed prior to save");
26065 ShowMessage(
"Can't save: extension must be either '.dev', or '.rly' with railway ready for operation");
26067 Screen->Cursor = TCursor(-2);
26104 System::WideChar ValidityBuffer[14];
26105 Clipboard()->GetTextBuf(ValidityBuffer, 14);
26107 Clipboard()->Close();
26164 catch(
const EClipboardException &e)
26223 bool TextFound =
false;
26248 AnsiString(VPos) +
"," + AnsiString((
short)UseEnteredPosition));
26249 int VPosHi, VPosLo, TextPosHi, TextPosLo;
26252 if(!UseEnteredPosition)
26259 int Depth = abs(Font->Height);
26260 TextPosHi = VPosHi + 20;
26261 TextPosLo = VPosLo - Depth - 4;
26264 if(TextPosLo >= ScreenPosLo)
26268 else if(TextPosHi < ScreenPosHi)
26274 VPos = ScreenPosLo + 288;
26299 catch(
const Exception &e)
26353 AnsiString OpTimeToActDisplay;
26354 AnsiString OpTimeToActString;
26355 AnsiString HeadCode;
26356 float OpTimeToActFloat;
26368 HeadCode = HCandTrainPosParam.first;
26370 if(HCandTrainPosParam.second >= 0)
26375 HeadCode += AnsiString(
'+');
26379 if(OpTimeToActFloat < 0.25)
26381 OpTimeToActString =
"NOW";
26383 else if(OpTimeToActFloat < 1)
26385 OpTimeToActString =
"<1";
26389 OpTimeToActString = AnsiString(floor(OpTimeToActFloat));
26391 if(OpTimeToActFloat < 60)
26393 OpTimeToActDisplay = HeadCode + AnsiString(
'\t') + OpTimeToActString;
26464 TPicture *PicPtr =
new TPicture;
26466 UGME.second = PicPtr;
26481 catch(
const EInvalidGraphic &e)
26484 "Incorrect file format, the file can't be loaded.\nEnsure that the file you want is a valid graphic file with extension .bmp, .gif, .jpg, or .png");
26487 catch(
const Exception &e)
26502 std::wstringstream wss;
26505 wss <<
"RlyClpBrdCopy\n";
26509 wss <<
"RlyClpBrd_Cut\n";
26514 wss << TTVIt->SpeedTag;
26516 for(
int AnsLen = 0; AnsLen <= TTVIt->ActiveTrackElementName.Length(); AnsLen++)
26518 if((TTVIt->ActiveTrackElementName).c_str()[AnsLen] !=
'\0')
26520 wss << (TTVIt->ActiveTrackElementName).c_str()[AnsLen];
26527 for(
int AnsLen = 0; AnsLen <= TTVIt->ElementID.Length(); AnsLen++)
26529 if((TTVIt->ElementID).c_str()[AnsLen] !=
'\0')
26531 wss << (TTVIt->ElementID).c_str()[AnsLen];
26538 for(
int AnsLen = 0; AnsLen <= TTVIt->LocationName.Length(); AnsLen++)
26540 if((TTVIt->LocationName).c_str()[AnsLen] !=
'\0')
26542 wss << (TTVIt->LocationName).c_str()[AnsLen];
26549 wss << TTVIt->CallingOnSet;
26551 wss << TTVIt->LCPlotted;
26559 wss << TTVIt->Attribute;
26561 wss << TTVIt->Conn[0];
26563 wss << TTVIt->Conn[1];
26565 wss << TTVIt->Conn[2];
26567 wss << TTVIt->Conn[3];
26569 wss << TTVIt->ConnLinkPos[0];
26571 wss << TTVIt->ConnLinkPos[1];
26573 wss << TTVIt->ConnLinkPos[2];
26575 wss << TTVIt->ConnLinkPos[3];
26577 wss << TTVIt->HLoc;
26579 wss << TTVIt->VLoc;
26581 wss << TTVIt->Length01;
26583 wss << TTVIt->Length23;
26585 wss << TTVIt->SpeedLimit01;
26587 wss << TTVIt->SpeedLimit23;
26589 wss << TTVIt->StationEntryStopLinkPos1;
26591 wss << TTVIt->StationEntryStopLinkPos2;
26593 wss << TTVIt->StationEntryStopLinkPos3;
26595 wss << TTVIt->StationEntryStopLinkPos4;
26597 wss << TTVIt->TrainIDOnElement;
26599 wss << TTVIt->TrainIDOnBridgeOrFailedPointOrigSpeedLimit01;
26601 wss << TTVIt->TrainIDOnBridgeOrFailedPointOrigSpeedLimit23;
26603 wss << int(TTVIt->SigAspect);
26606 wss <<
"$$$" <<
'\n';
26612 for(
int AnsLen = 0; AnsLen <= TTVIt->TextString.Length(); AnsLen++)
26614 if((TTVIt->TextString).c_str()[AnsLen] !=
'\0')
26616 wss << (TTVIt->TextString).c_str()[AnsLen];
26623 wss << TTVIt->HPos;
26625 wss << TTVIt->VPos;
26627 for(
int AnsLen = 0; AnsLen <= AnsiString(TTVIt->Font->Name).Length(); AnsLen++)
26629 if(AnsiString(TTVIt->Font->Name).c_str()[AnsLen] !=
'\0')
26631 wss << AnsiString(TTVIt->Font->Name).c_str()[AnsLen];
26638 wss << TTVIt->Font->Size;
26640 if((TTVIt->Font->Color < 0) || (TTVIt->Font->Color > 0xFFFFFF))
26646 wss << int(TTVIt->Font->Color) <<
'\n';
26648 wss << int(TTVIt->Font->Charset) <<
'\n';
26651 wss <<
"$$$" <<
'\n';
26662 wss <<
"$$$" <<
'\n';
26671 wss << PDVIt->GetTrackVectorPosition();
26673 wss << PDVIt->GetHLoc();
26675 wss << PDVIt->GetVLoc();
26677 wss << PDVIt->GetELink();
26679 wss << PDVIt->GetELinkPos();
26681 wss << PDVIt->GetXLink();
26683 wss << PDVIt->GetXLinkPos();
26685 wss << PDVIt->GetEXNumber();
26689 wss <<
"$$$" <<
'\n';
26692 Clipboard()->Clear();
26693 Clipboard()->SetTextBuf(&(wss.str()[0]));
26694 Clipboard()->Close();
26699 catch(
const EClipboardException &e)
26706 catch(
const Exception &e)
26721 ValidResult =
false;
26722 System::WideChar *SelectVectorBuffer =
new System::WideChar[4000000];
26723 int StreamSize = 0;
26724 StreamSize = Clipboard()->GetTextBuf(SelectVectorBuffer, 4000000);
26725 Clipboard()->Clear();
26726 Clipboard()->Close();
26727 if(StreamSize < 14)
26732 std::wstringstream wss;
26733 wss << SelectVectorBuffer;
26734 ClpBrdValid = AnsiString(SelectVectorBuffer).SubString(1, 13);
26736 delete[]SelectVectorBuffer;
26743 int MarkerCounter = 0;
26745 wchar_t LineString[1000];
26750 wss.getline(LineString, 100);
26757 wss.getline(LineString, 100);
26758 if(AnsiString(LineString) ==
"$$$")
26765 wss.getline(LineString, 100);
26767 wss.getline(LineString, 100);
26769 wss.getline(LineString, 100);
26772 wss.getline(LineString, 100);
26774 wss.getline(LineString, 100);
26775 TE.
LCPlotted = AnsiString(LineString).ToInt();
26782 wss.getline(LineString, 100);
26783 TE.
Attribute = AnsiString(LineString).ToInt();
26784 wss.getline(LineString, 100);
26785 TE.
Conn[0] = AnsiString(LineString).ToInt();
26786 wss.getline(LineString, 100);
26787 TE.
Conn[1] = AnsiString(LineString).ToInt();
26788 wss.getline(LineString, 100);
26789 TE.
Conn[2] = AnsiString(LineString).ToInt();
26790 wss.getline(LineString, 100);
26791 TE.
Conn[3] = AnsiString(LineString).ToInt();
26792 wss.getline(LineString, 100);
26793 TE.
ConnLinkPos[0] = AnsiString(LineString).ToInt();
26794 wss.getline(LineString, 100);
26795 TE.
ConnLinkPos[1] = AnsiString(LineString).ToInt();
26796 wss.getline(LineString, 100);
26797 TE.
ConnLinkPos[2] = AnsiString(LineString).ToInt();
26798 wss.getline(LineString, 100);
26799 TE.
ConnLinkPos[3] = AnsiString(LineString).ToInt();
26800 wss.getline(LineString, 100);
26801 TE.
HLoc = AnsiString(LineString).ToInt();
26802 wss.getline(LineString, 100);
26803 TE.
VLoc = AnsiString(LineString).ToInt();
26804 wss.getline(LineString, 100);
26805 TE.
Length01 = AnsiString(LineString).ToInt();
26806 wss.getline(LineString, 100);
26807 TE.
Length23 = AnsiString(LineString).ToInt();
26808 wss.getline(LineString, 100);
26810 wss.getline(LineString, 100);
26812 wss.getline(LineString, 100);
26814 wss.getline(LineString, 100);
26816 wss.getline(LineString, 100);
26818 wss.getline(LineString, 100);
26820 wss.getline(LineString, 100);
26822 wss.getline(LineString, 100);
26824 wss.getline(LineString, 100);
26827 wss.getline(LineString, 100);
26828 int temp = AnsiString(LineString).ToInt();
26849 SelectTrackMapKeyPair.first = TE.
HLoc;
26850 SelectTrackMapKeyPair.second = TE.
VLoc;
26851 SelectTrackMapEntry.first = SelectTrackMapKeyPair;
26853 SelectTrackMap.insert(SelectTrackMapEntry);
26858 AnsiString FontName;
26859 int FontSize, FontColour, FontCharset, FontStyle;
26862 wss.getline(LineString, 1000);
26863 if(AnsiString(LineString) ==
"$$$")
26871 wss.getline(LineString, 1000);
26872 TI.
HPos = AnsiString(LineString).ToInt();
26873 wss.getline(LineString, 1000);
26874 TI.
VPos = AnsiString(LineString).ToInt();
26875 wss.getline(LineString, 1000);
26876 FontName = AnsiString(LineString).c_str();
26877 wss.getline(LineString, 1000);
26878 FontSize = AnsiString(LineString).ToInt();
26879 wss.getline(LineString, 1000);
26880 FontColour = AnsiString(LineString).ToInt();
26881 wss.getline(LineString, 1000);
26882 FontCharset = AnsiString(LineString).ToInt();
26883 wss.getline(LineString, 1000);
26884 FontStyle = AnsiString(LineString).ToInt();
26886 TFont *NewFont =
new TFont;
26887 NewFont->Name = FontName;
26888 NewFont->Size = FontSize;
26889 NewFont->Color =
static_cast<TColor
>(FontColour);
26890 NewFont->Charset = FontCharset;
26897 wss.getline(LineString, 100);
26898 SelectBitmap->Height = AnsiString(LineString).ToInt();
26899 wss.getline(LineString, 100);
26901 wss.getline(LineString, 100);
26902 SelectRect.left = AnsiString(LineString).ToInt();
26903 wss.getline(LineString, 100);
26904 SelectRect.top = AnsiString(LineString).ToInt();
26905 wss.getline(LineString, 100);
26906 if(AnsiString(LineString) ==
"$$$")
26913 int TempTVPos, TempHLoc, TempVLoc, TempELink, TempELinkPos, TempXLink, TempXLinkPos, TempEXNumber, ATVecPos;
26918 wss.getline(LineString, 100);
26919 if(AnsiString(LineString) ==
"$$$")
26925 TempTVPos = AnsiString(LineString).ToInt();
26926 wss.getline(LineString, 100);
26927 TempHLoc = AnsiString(LineString).ToInt();
26928 wss.getline(LineString, 100);
26929 TempVLoc = AnsiString(LineString).ToInt();
26930 wss.getline(LineString, 100);
26931 TempELink = AnsiString(LineString).ToInt();
26932 wss.getline(LineString, 100);
26933 TempELinkPos = AnsiString(LineString).ToInt();
26934 wss.getline(LineString, 100);
26935 TempXLink = AnsiString(LineString).ToInt();
26936 wss.getline(LineString, 100);
26937 TempXLinkPos = AnsiString(LineString).ToInt();
26938 wss.getline(LineString, 100);
26939 TempEXNumber = AnsiString(LineString).ToInt();
26948 TempPrefDirElement.
SetELink(TempELink);
26950 TempPrefDirElement.
SetXLink(TempXLink);
26957 if(MarkerCounter == 4)
26959 ValidResult =
true;
26964 catch(
const EClipboardException &e)
26966 ValidResult =
false;
26970 catch(
const Exception &e)
26972 ValidResult =
false;
27011 DelayMenu->Caption =
"Moderate delays";
27127 std::advance(OACurrentEntryPtr, OAIndex);
27142 int TrainIDorTVPos = OACurrentEntryPtr->second.second;
27143 if(TrainIDorTVPos >= 0)
27149 TrainID = TrainIDorTVPos;
27160 TrackVectorPosition = -(TrainIDorTVPos + 1);
27201 MPHPGeneralLabel->Caption =
"Complete the boxes and press 'Enter' for each.";
27210 catch(
const EIdException &e)
27212 ShowMessage(
"MultiplayerHostSessionMenuItemClick " + e.Message);
27215 catch(
const Exception &e)
27253 bool RailwayFound =
false;
27262 RailwayFound =
true;
27268 ShowMessage(
"Can't find '" +
RailwayTitle +
"' in coupling file - please load an appropriate railway and timetable or a pre-start session file");
27275 int GridCount = 2; ;
27278 unsigned char x = 1;
27312 catch(
const EIdException &e)
27314 ShowMessage(
"MPHPLoadCouplingFileButtonClick " + e.Message);
27317 catch(
const Exception &e)
27342 catch(
const EIdException &e)
27344 ShowMessage(
"MPHPCancelButtonClick " + e.Message);
27347 catch(
const Exception &e)
27361 ShowMessage(
"We're off!");
27368 catch(
const EIdException &e)
27370 ShowMessage(
"MPHPStartButtonClick " + e.Message);
27373 catch(
const Exception &e)
27391 ShowMessage(
"Format should be 'a.b.c.d' where a, b, c, and d are numbers between 0 and 255.\n\nObtain the address from the host and enter exactly as given.");
27411 ShowMessage(
"Format should be 'a.b.c.d' where a, b, c, and d are numbers between 0 and 255.\n\nObtain the address from the host and enter exactly as given.");
27420 catch(
const EIdException &e)
27422 ShowMessage(
"MPHPOwnIPEditBoxKeyUp " + e.Message);
27425 catch(
const Exception &e)
27443 ShowMessage(
"Entry should be a number between 49152 and 59999.");
27463 ShowMessage(
"Entry should be a number between 49152 and 59999.");
27472 catch(
const EIdException &e)
27474 ShowMessage(
"MPHPOwnPortEditBoxKeyUp " + e.Message);
27477 catch(
const Exception &e)
27486 TSysLinkType LinkType)
27488 if(LinkType == sltURL)
27490 ::ShellExecute(Handle, NULL, Link.c_str(), NULL, NULL, SW_SHOWNORMAL);
27498 if(lower.first < higher.first)
27502 else if(lower.first > higher.first)
27506 else if(lower.second.first < higher.second.first)
27510 else if(lower.second.first > higher.second.first)
27514 else if(lower.second.second < higher.second.second)
27518 else return(
false);
27527 if(lower.first < higher.first)
27531 else if(lower.first > higher.first)
27535 else if(lower.second.first < higher.second.first)
27539 else if(lower.second.first > higher.second.first)
27543 else if(lower.second.second < higher.second.second)
27547 else if(lower.second.second > higher.second.second)
27551 else return(
false);
27563 AnsiString RailwayName1 =
"", RailwayName2 =
"", OneLine =
"", ExitID1 =
"", ExitID2 =
"";
27564 int HLoc1, HLoc2, VLoc1, VLoc2, CPos, NumRailways;
27569 std::ifstream TxtFile(FileName.c_str());
27570 AnsiString SyntaxError =
"Coupling file error - structure should consist of lines of 'R1; exit1ID; R2; exit2ID' and so on "
27571 "for all coupled exits, where R1 and R2 are railway names without the '.rly' extension, exit1ID is an "
27572 "exit ID in R1, and exit2ID is an exit ID in R2";
27575 ShowMessage(
"Can't find the coupling file. Please make sure it's located in the directory selected and has a .txt extension");
27579 while(!TxtFile.eof())
27583 ShowMessage(SyntaxError);
27588 if(TxtFile.eof() && (OneLine ==
""))
27592 if(OneLine.AnsiPos(
',') != 0)
27594 ShowMessage(SyntaxError);
27603 int DelimPos = OneLine.Pos(
';');
27606 ShowMessage(SyntaxError);
27613 RailwayName1 = OneLine.SubString(1, (DelimPos - 1));
27614 OneLine = OneLine.SubString(DelimPos + 1, OneLine.Length() - DelimPos);
27615 if(RailwayName1.LowerCase().SubString(RailwayName1.Length() - 3, 4) ==
".rly")
27617 RailwayName1 = RailwayName1.SubString(1, RailwayName1.Length() - 4);
27620 DelimPos = OneLine.Pos(
';');
27623 ShowMessage(SyntaxError);
27630 ExitID1 = OneLine.SubString(1, (DelimPos - 1));
27631 OneLine = OneLine.SubString(DelimPos + 1, OneLine.Length() - DelimPos);
27639 DelimPos = OneLine.Pos(
';');
27642 ShowMessage(SyntaxError);
27649 RailwayName2 = OneLine.SubString(1, (DelimPos - 1));
27650 OneLine = OneLine.SubString(DelimPos + 1, OneLine.Length() - DelimPos);
27651 if(RailwayName2.LowerCase().SubString(RailwayName2.Length() - 3, 4) ==
".rly")
27653 RailwayName2 = RailwayName2.SubString(1, RailwayName2.Length() - 4);
27658 ShowMessage(SyntaxError);
27673 AnsiCouplingPair1.first = RailwayName1;
27674 AnsiCouplingPair1.second = HVExitPair1;
27675 AnsiCouplingPair2.first = RailwayName2;
27676 AnsiCouplingPair2.second = HVExitPair2;
27677 AnsiCouplingMapEntry.first = AnsiCouplingPair1;
27678 AnsiCouplingMapEntry.second = AnsiCouplingPair2;
27680 AnsiCouplingMapEntry.first = AnsiCouplingPair2;
27681 AnsiCouplingMapEntry.second = AnsiCouplingPair1;
27700 int ListCounter = 1;
27703 if(ACMIt->first.first == *
RLIt)
27705 NumHVPair1.first = ListCounter;
27706 NumHVPair1.second = ACMIt->first.second;
27714 if(ACMIt->second.first == *
RLIt)
27716 NumHVPair2.first = ListCounter;
27717 NumHVPair2.second = ACMIt->second.second;
27732 DMEntry.first = CMIt->first;
27733 DMEntry.second = ServiceInfo;
27736 ShowMessage(
"File loaded successfully");
27746 AnsiString HString =
"", VString =
"";
27749 ShowMessage(
"Coupling file error - an exit ID is missing from the file");
27753 for(
int x = 1; x <= HVID.Length(); x++)
27756 if(((C <
'0') || (C >
'9')) && (C !=
'N') && (C !=
'-'))
27758 ShowMessage(
"Coupling file error - an exit ID contains illegal characters, can only include digits, '-' or 'N'");
27763 int DashPos = HVID.Pos(
'-');
27766 ShowMessage(
"Coupling file error - structure should consist of lines of 'R1, exit1 ID, R2, corresponding exit ID' and so on "
27767 "for all coupled exits, where R1 and R2 are railway names without the '.rly' extension");
27773 HString = HVID.SubString(1, DashPos - 1);
27774 VString = HVID.SubString(DashPos + 1, HVID.Length() - DashPos);
27775 if(HString[1] ==
'N')
27777 HString = HString.SubString(2, HString.Length() - 1);
27778 HVPair.first = -HString.ToInt();
27782 HVPair.first = HString.ToInt();
27784 if(VString[1] ==
'N')
27786 VString = VString.SubString(2, VString.Length() - 1);
27787 HVPair.second = -VString.ToInt();
27791 HVPair.second = VString.ToInt();
27804 bool Listed =
false, Available =
false, RetType =
false;
27821 else if(!Available)
27839 TCouplingMap::iterator CMIt;
27843 if(CMIt->first.first == PlayerNumber)
27852 return(Count * 10);
27865 UnicodeString Data =
"";
27866 UnicodeString PeerIP =
"";
27867 unsigned short PeerPort = 0;
27868 unsigned char marker;
27869 bool Found1 =
false, Found2 =
false;
27870 AnsiString PlayerRailwayName, PlayerUserName;
27872 UnicodeString Message1 =
"The railway doesn't appear in the coupled group - the host can advise which railways are valid";
27873 UnicodeString Message2 =
"The railway has already been allocated - the host can advise which are still available";
27875 HostBuffer.Length = 8192;
27876 HostBuffer.Length =
MPHostClient->ReceiveBuffer(HostBuffer, PeerIP, PeerPort, 10);
27879 if(HostBuffer.Length != 0)
27881 if(HostBuffer[0] ==
'1')
27884 bool FoundFlag =
false;
27885 for(
int x = 1; x < HostBuffer.Length; x++)
27887 if((HostBuffer[x] ==
';') && (x > 1) && (x < (HostBuffer.Length - 1)))
27898 for(
int x = 1; x < HostBuffer.Length; x++)
27900 if((HostBuffer[x] <
' ') || (HostBuffer[x] >
'~'))
27907 Data = BytesToString(HostBuffer);
27908 int DelimPos = Data.Pos(
';');
27909 PlayerUserName = Data.SubString(2, DelimPos - 2);
27910 PlayerRailwayName = Data.SubString(DelimPos + 1, Data.Length() - DelimPos);
27911 unsigned char PlayerNumber;
27912 if(!
RlyToNum(PlayerRailwayName, PlayerNumber))
27914 ShowMessage(
"Error in converting incoming information for player '" + PlayerUserName +
"', ask player to cancel and join again");
27923 UnicodeString RejectString = PlayerUserName +
" is asking to join with railway " + PlayerRailwayName +
". OK to join?";
27924 int button = Application->MessageBox(RejectString.c_str(), L
"Request", MB_YESNO);
27927 MPHostClient->SendBuffer(PeerIP, PeerPort, ToBytes(
"The host did not accept your request to join"));
27944 if(
InfoVector.at(x).RailwayName == PlayerRailwayName)
27953 if(!Found1 || !Found2)
27956 ShowMessage(
"Error in initial contact information for player '" + PlayerUserName +
"', ask player to cancel and join again");
27966 HVbuffer.Length = NumBytes;
27967 for(
int x = 0; x < NumBytes; x += 10)
27969 HVbuffer[x] = CMIt->first.first;
27970 HVbuffer[x + 1] = CMIt->first.second.first & 0x00FF;
27971 HVbuffer[x + 2] = (CMIt->first.second.first & 0xFF00) / 256;
27972 HVbuffer[x + 3] = CMIt->first.second.second & 0x00FF;
27973 HVbuffer[x + 4] = (CMIt->first.second.second & 0xFF00) / 256;
27975 HVbuffer[x + 5] = CMIt->second.first;
27976 HVbuffer[x + 6] = CMIt->second.second.first & 0x00FF;
27977 HVbuffer[x + 7] = (CMIt->second.second.first & 0xFF00) / 256;
27978 HVbuffer[x + 8] = CMIt->second.second.second & 0x00FF;
27979 HVbuffer[x + 9] = (CMIt->second.second.second & 0xFF00) / 256;
27990 if(ErrorNumber == 1)
27992 MPHostClient->SendBuffer(PeerIP, PeerPort, ToBytes(Message1));
27994 else if(ErrorNumber == 2)
27996 MPHostClient->SendBuffer(PeerIP, PeerPort, ToBytes(Message2));
28001 else if(HostBuffer[0] ==
'2')
28003 TDynamicMap::iterator DMIt, HMIt;
28012 HMIt->second = DMIt->second;
28016 ShowMessage(
"Failed to locate player information in host database for player '" + PlayerUserName +
"', ask player to cancel and join again");
28041 if(
InfoVector.at(x).UserName == PlayerUserName)
28048 if(!Found1 || !Found2)
28051 ShowMessage(
"Error in 'ready to begin' contact information for player '" + PlayerUserName +
"', ask player to cancel and join again");
28058 HVbuffer.Length = 22;
28059 UnicodeString Message =
"Await simulation start";
28060 HVbuffer = ToBytes(Message);
28064 bool AllReady =
true;
28077 else if(HostBuffer[0] ==
'3')
28079 for(
int x = 1; x < HostBuffer.Length; x++)
28081 if((HostBuffer[x] <
' ') || (HostBuffer[x] >
'~'))
28087 Data = BytesToString(HostBuffer);
28088 PlayerUserName = Data.SubString(2, Data.Length() - 1);
28090 HVbuffer.Length = 9;
28091 UnicodeString Message =
"Cancelled";
28092 HVbuffer = ToBytes(Message);
28095 unsigned char RlyUserNumber;
28096 if(!
UserToNum(PlayerUserName, RlyUserNumber))
28103 ShowMessage(
"Player '" + PlayerUserName +
"', has cancelled the join request");
28109 else if(HostBuffer[0] ==
'4')
28113 for(
int x = 1; x < HostBuffer.Length; x++)
28115 if((HostBuffer[x] <
' ') || (HostBuffer[x] >
'~'))
28121 Data = BytesToString(HostBuffer);
28122 PlayerUserName = Data.SubString(2, Data.Length() - 1);
28124 HVbuffer.Length = 13;
28125 UnicodeString Message =
"Start Session";
28126 HVbuffer = ToBytes(Message);
28133 else if(HostBuffer[0] ==
'5')
28135 TDynamicMap::iterator DMIt, HMIt;
28144 HMIt->second = DMIt->second;
28149 unsigned char RlyUserNumber;
28150 if(!
UserToNum(PlayerUserName, RlyUserNumber))
28156 bool LoadingFlag =
false;
28160 if(HMIt->first.first == RlyUserNumber)
28163 LoadingFlag =
true;
28165 if(LoadingFlag && (HMIt->first.first != RlyUserNumber))
28172 HVbuffer.Length = 8192;
28188 catch(
const EIdException &e)
28193 catch(
const Exception &e)
28214 MPCPLabel2->Caption =
"Complete the boxes and press 'Enter' for each.";
28215 MPCPLabel4->Caption =
"Joining request not yet sent";
28216 MPCPLabel7->Caption =
"Only click 'Send' when the host is ready - the host will";
28217 MPCPLabel8->Caption =
"advise by communicating outside the game.";
28218 MPCPLabel5->Caption =
"Host IP address (obtain from host)";
28219 MPCPLabel6->Caption =
"Host port number (obtain from host)";
28220 MPCPLabel3->Caption =
"Player name (2 to 4 characters)";
28252 catch(
const Exception &e)
28266 MPCPLabel2->Caption =
"Await host response then click 'Ready to begin'";
28267 MPCPLabel4->Caption =
"Awaiting host response";
28283 catch(
const Exception &e)
28313 catch(
const Exception &e)
28327 int button = Application->MessageBox(L
"This will transfer all timer controls to the host.\n\n Click 'Yes' to wait for the host to start the simulation.\n\nOK to proceed?", L
"Warning!", MB_YESNO | MB_ICONWARNING);
28353 catch(
const Exception &e)
28371 ShowMessage(
"Format should be 'a.b.c.d' where a, b, c, and d are numbers between 0 and 255.\n\nObtain the address from the host and enter exactly as given.");
28393 ShowMessage(
"Format should be 'a.b.c.d' where a, b, c, and d are numbers between 0 and 255.\n\nObtain the address from the host and enter exactly as given.");
28402 catch(
const Exception &e)
28421 ShowMessage(
"Entry should be a number between 49152 and 59999.\n\nObtain the port number from the host and enter exactly as given.");
28440 ShowMessage(
"Entry should be a number between 49152 and 59999.\n\nObtain the port number from the host and enter exactly as given.");
28449 catch(
const Exception &e)
28462 MPCPLabel3->Caption =
"Player name (2 to 4 characters)";
28469 ShowMessage(
"Entry should have at least two and at most four characters with no numbers or special characters.");
28493 ShowMessage(
"Entry should have at least two and at most four characters with no numbers or special characters.");
28503 catch(
const Exception &e)
28516 buffer.Length = 8192;
28517 buffer[0] = marker;
28518 for(bufCounter = 1; bufCounter <= UserName.Length(); bufCounter++)
28520 buffer[bufCounter] = UserName[bufCounter];
28522 if(UserName.Length() < 4)
28524 buffer[bufCounter] =
';';
28531 for(TDynamicMap::iterator DMIt = DynamicMap.begin(); DMIt != DynamicMap.end(); DMIt++)
28533 buffer[bufCounter] = DMIt->first.first;
28535 buffer[bufCounter] = DMIt->first.second.first & 0x00FF;
28537 buffer[bufCounter] = (DMIt->first.second.first & 0xFF00) / 256;
28539 buffer[bufCounter] = DMIt->first.second.second & 0x00FF;
28541 buffer[bufCounter] = (DMIt->first.second.second & 0xFF00) / 256;
28543 DMIt->second.ServiceReference = DMIt->second.ServiceReference.Trim();
28544 for(
int x = 1; x <= DMIt->second.ServiceReference.Length(); x++)
28546 buffer[bufCounter] = DMIt->second.ServiceReference[x];
28549 if(DMIt->second.ServiceReference.Length() < 8)
28551 buffer[bufCounter] =
';';
28554 buffer[bufCounter] = DMIt->second.RepeatNumber & 0x00FF;
28556 buffer[bufCounter] = (DMIt->second.RepeatNumber & 0xFF00) / 256;
28558 buffer[bufCounter] = DMIt->second.TimeToExitSecs & 0x00FF;
28560 buffer[bufCounter] = (DMIt->second.TimeToExitSecs & 0xFF00) / 256;
28569 buffer.Length = bufCounter;
28583 marker = Buffer[0];
28585 for(
int x = 1; x < 5; x++)
28587 if((Buffer[x] <
' ') || (Buffer[x] >
'~'))
28593 if(Buffer[x] ==
';')
28598 UserName[1] = Buffer[1];
28599 UserName[2] = Buffer[2];
28600 if(UserName[2] ==
';')
28602 UserName.Delete(2,3);
28607 UserName[3] = Buffer[3];
28608 if(UserName[3] ==
';')
28610 UserName.Delete(3,2);
28615 UserName[4] = Buffer[4];
28616 if(UserName[4] ==
';')
28618 UserName.Delete(4,1);
28623 while(y < (Buffer.Length - 9))
28626 NumHVPair.first = Buffer[y];
28627 NumHVPair.second.first = Buffer[y+ 1] + (256 * Buffer[y + 2]);
28628 NumHVPair.second.second = Buffer[y + 3] + (256 * Buffer[y + 4]);
28637 while((Buffer[y + z] !=
';') && (z < 8))
28644 if(Buffer[y] ==
';')
28648 ServInfo.
RepeatNumber = Buffer[y] + (256 * Buffer[y + 1]);
28649 ServInfo.
TimeToExitSecs = Buffer[y + 2] + (256 * Buffer[y + 3]);
28657 DMEntry.first = NumHVPair;
28658 DMEntry.second = ServInfo;
28659 DMap.insert(DMEntry);
28670 int bufCounter = 0;
28671 buffer.Length = 8192;
28673 buffer[0] = TTTime % 256;
28675 buffer[1] = TTTime % 256;
28677 buffer[2] = TTTime % 256;
28679 buffer[3] = TTTime % 256;
28681 for(TDynamicMap::iterator DMIt = DynamicMap.begin(); DMIt != DynamicMap.end(); DMIt++)
28683 buffer[bufCounter] = DMIt->first.first;
28685 buffer[bufCounter] = DMIt->first.second.first & 0x00FF;
28687 buffer[bufCounter] = (DMIt->first.second.first & 0xFF00) / 256;
28689 buffer[bufCounter] = DMIt->first.second.second & 0x00FF;
28691 buffer[bufCounter] = (DMIt->first.second.second & 0xFF00) / 256;
28693 DMIt->second.ServiceReference = DMIt->second.ServiceReference.Trim();
28694 for(
int x = 1; x <= DMIt->second.ServiceReference.Length(); x++)
28696 buffer[bufCounter] = DMIt->second.ServiceReference[x];
28699 if(DMIt->second.ServiceReference.Length() < 8)
28701 buffer[bufCounter] =
';';
28704 buffer[bufCounter] = DMIt->second.RepeatNumber & 0x00FF;
28706 buffer[bufCounter] = (DMIt->second.RepeatNumber & 0xFF00) / 256;
28708 buffer[bufCounter] = DMIt->second.TimeToExitSecs & 0x00FF;
28710 buffer[bufCounter] = (DMIt->second.TimeToExitSecs & 0xFF00) / 256;
28713 buffer.Length = bufCounter;
28726 TTTime = Buffer[0] + (256 * Buffer[1]) + (65536 * Buffer[2]) + (16777216 * Buffer[3]);
28727 if((TTTime < 0) || (TTTime > 34560000))
28733 while(y < (Buffer.Length - 9))
28736 NumHVPair.first = Buffer[y];
28743 NumHVPair.second.first = Buffer[y+ 1] + (256 * Buffer[y + 2]);
28744 NumHVPair.second.second = Buffer[y + 3] + (256 * Buffer[y + 4]);
28753 while((Buffer[y + z] !=
';') && (z < 8))
28760 if(Buffer[y] ==
';')
28764 ServInfo.
RepeatNumber = Buffer[y] + (256 * Buffer[y + 1]);
28765 ServInfo.
TimeToExitSecs = Buffer[y + 2] + (256 * Buffer[y + 3]);
28773 DMEntry.first = NumHVPair;
28774 DMEntry.second = ServInfo;
28775 DMap.insert(DMEntry);
28789 unsigned char UserNum;
28790 while(!ExitFile.eof())
28792 ExitFile >> UserNum;
28798 ExitFile >> ShortPair.first;
28803 ExitFile >> ShortPair.second;
28808 DMapEntry.first.first = UserNum;
28809 DMapEntry.first.second = ShortPair;
28810 DMapEntry.second = ServiceInfo;
28811 DMap.insert(DMapEntry);
28825 TDynamicMap::iterator DMIt;
28832 NumHVPair.second = TTEMMIt->first;
28833 DMIt = DMap.find(NumHVPair);
28834 if(DMIt != DMap.end())
28836 DMIt->second.ServiceReference = TTEMMIt->second.ServiceReference.Trim();
28837 DMIt->second.RepeatNumber = TTEMMIt->second.RepeatNumber;
28838 DMIt->second.TimeToExitSecs = TTEMMIt->second.TimeToExitSecs;
28851 int Dot1 = 0, Dot2 = 0, Dot3 = 0;
28852 AnsiString Num1 =
"",Num2 =
"",Num3 =
"",Num4 =
"";
28853 if(Text.Length() < 7)
28857 for(
int x = 1; x <= Text.Length(); x++)
28875 if((Dot1 ==0) || (Dot2 ==0) || (Dot3 ==0))
28879 if(Text.Length() == Dot3)
28883 Num1 = Text.SubString(1, Dot1 - 1);
28884 Num2 = Text.SubString(Dot1 + 1, Dot2 - Dot1 - 1);
28885 Num3 = Text.SubString(Dot2 + 1, Dot3 - Dot2 - 1);
28886 Num4 = Text.SubString(Dot3 + 1, Text.Length() - Dot3);
28887 if((Num1 ==
"") || (Num2 ==
"") || (Num3 ==
"") || (Num4 ==
""))
28891 if((Num1.ToInt() > 255) ||(Num2.ToInt() > 255) ||(Num3.ToInt() > 255) ||(Num4.ToInt() > 255))
28895 if((Num1.ToInt() < 0) ||(Num2.ToInt() < 0) ||(Num3.ToInt() < 0) ||(Num4.ToInt() < 0))
28901 catch(
const EConvertError &e)
28911 ServiceReference =
" ";
28913 TimeToExitSecs = -1;
28938 if(IVIt->RailwayName == RailwayName)
28940 RlyUserNumber = IVIt->RlyUserNumber;
28958 if(IVIt->UserName == UserName)
28960 RlyUserNumber = IVIt->RlyUserNumber;
28978 if(IVIt->RlyUserNumber == RlyUserNumber)
28980 RailwayName = IVIt->RailwayName;
28998 if(IVIt->UserName == UserName)
29000 UserIP = IVIt->UserIP;
29001 UserPort = IVIt->UserPort;
29019 if(IVIt->RlyUserNumber == RlyUserNumber)
29021 UserIP = IVIt->UserIP;
29022 UserPort = IVIt->UserPort;
29033 if(NumHVPair.first > 100)
29037 if((NumHVPair.second.first > 2000) || (NumHVPair.second.first < -2000))
29041 if((NumHVPair.second.second > 2000) || (NumHVPair.second.second < -2000))
29056 if((RepeatNumber < 0) || (RepeatNumber > 6000))
29060 if((TimeToExitSecs < -1) || (TimeToExitSecs > 3600))
29085 if(
InfoVector.at(x).UserName == PlayerUserName)
29175 UnicodeString Data = UnicodeString(
'3') +
MPCPUserName;
29182 UnicodeString Data = UnicodeString(
'4') +
MPCPUserName;
29188 UnicodeString Data = UnicodeString(
'6') +
MPCPUserName;
29199 Buffer.Length = 8192;
29201 if(Buffer.Length != 0)
29204 if((Buffer[0] ==
'T') && (Buffer[1] ==
'h') && (Buffer[2] ==
'e'))
29206 UnicodeString HostMessage = BytesToString(Buffer);
29207 ShowMessage(HostMessage);
29225 unsigned char UserNumber;
29230 for(
int x = 0; x < (Buffer.Length - 9); x += 10)
29232 UserNumber = Buffer[x];
29233 ShortPair.first = Buffer[x + 1] + (256 * Buffer[x + 2]);
29234 ShortPair.second = Buffer[x + 3] + (256 * Buffer[x + 4]);
29235 DMEntry.first.first = UserNumber;
29236 DMEntry.first.second = ShortPair;
29237 DMEntry.second = ServiceInfo;
29239 UserNumber = Buffer[x + 5];
29240 ShortPair.first = Buffer[x + 6] + (256 * Buffer[x + 7]);
29241 ShortPair.second = Buffer[x + 8] + (256 * Buffer[x + 9]);
29242 DMEntry.first.first = UserNumber;
29243 DMEntry.first.second = ShortPair;
29244 DMEntry.second = ServiceInfo;
29251 typedef std::pair<int, int> THLocVLocPair;
29252 THLocVLocPair HVPair;
29253 std::pair<THLocVLocPair, Graphics::TBitmap*> MPOMEntry;
29255 Graphics::TBitmap *GrPtr;
29256 HVPair.first = int(DMIt->first.second.first);
29257 HVPair.second = int(DMIt->first.second.second);
29259 if((SpeedTag < 80) || (SpeedTag > 87))
29261 throw Exception(
"Error, SpeedTag not a continuation in DynMapFromHost, value is " + AnsiString(SpeedTag));
29263 else if(SpeedTag == 80)
29267 else if(SpeedTag == 81)
29271 else if(SpeedTag == 82)
29275 else if(SpeedTag == 83)
29279 else if(SpeedTag == 84)
29283 else if(SpeedTag == 85)
29287 else if(SpeedTag == 86)
29291 else if(SpeedTag == 87)
29295 MPOMEntry.first = HVPair;
29296 MPOMEntry.second = GrPtr;
29300 MPCPLabel2->Caption =
"When ready click 'Ready to begin'";
29301 MPCPLabel4->Caption =
"Joining request accepted";
29313 Buffer.Length = 8192;
29315 if(Buffer.Length != 0)
29317 if(BytesToString(Buffer) ==
"Await simulation start")
29322 MPCPLabel2->Caption =
"Awaiting simulation start";
29348 Buffer.Length = 8192;
29350 if(Buffer.Length != 0)
29352 if(BytesToString(Buffer) ==
"Cancelled")
29362 Buffer.Length = 8192;
29364 if(Buffer.Length != 0)
29366 if(BytesToString(Buffer) ==
"Start Session")
29382 TDynamicMap::iterator DMIt, DMFHIt;
29383 Buffer.Length = 8192;
29385 if(Buffer.Length != 0)
29393 for(DMIt = DMap.begin(); DMIt != DMap.end(); DMIt++)
29398 DMFHIt->second = DMIt->second;
29412 catch(
const EIdException &e)
29417 catch(
const Exception &e)
29492 Screen->Cursor = TCursor(-11);
29493 InfoPanel->Caption =
"Please wait - element length heatmap being generated";
29506 InfoPanel->Caption =
"Track element length heatmap";
29507 Screen->Cursor = TCursor(-2);
29512 Screen->Cursor = TCursor(-11);
29517 Screen->Cursor = TCursor(-2);
29521 catch(
const Exception &e)
29537 Screen->Cursor = TCursor(-11);
29538 InfoPanel->Caption =
"Please wait - element speed limit heatmap being generated";
29551 InfoPanel->Caption =
"Track element speed limit heatmap";
29552 Screen->Cursor = TCursor(-2);
29557 Screen->Cursor = TCursor(-11);
29562 Screen->Cursor = TCursor(-2);
29566 catch(
const Exception &e)